[HN Gopher] A Python Guide for the Ages
___________________________________________________________________
A Python Guide for the Ages
Author : zombiemama
Score : 219 points
Date : 2021-12-25 02:29 UTC (20 hours ago)
(HTM) web link (gto76.github.io)
(TXT) w3m dump (gto76.github.io)
| asicsp wrote:
| Previous substantial discussion:
| https://news.ycombinator.com/item?id=19075325 _(Feb 4, 2019 | 81
| comments)_
|
| Other cheatsheets (excluding learnxinyminutes already mentioned
| in another comment)
|
| * Python Crash Course:
| https://ehmatthes.github.io/pcc_2e/cheat_sheets/cheat_sheets...
|
| * Scientific Python:
| https://ipgp.github.io/scientific_python_cheat_sheet/
| darkbatman wrote:
| Does someone know similar guide for javascript/node.js or its a
| good thing to start one?
| asicsp wrote:
| https://learnxinyminutes.com/docs/javascript/ might help
| (there's further reading links at the end as well)
| mark_l_watson wrote:
| Thanks for whoever did this, a nice resource! I have been forced
| to use Python for many years because I am mostly payed to do deep
| learning. I really enjoyed carefully reading through this. Good
| job.
| phoenix24 wrote:
| does anyone have recommendations for a good ruby cheatsheet?
| asicsp wrote:
| These might help:
|
| * https://learnxinyminutes.com/docs/ruby/
|
| *
| https://github.com/ThibaultJanBeyer/cheatsheets/blob/master/...
|
| * https://github.com/lifeparticle/Ruby-Cheatsheet
| abhishekjha wrote:
| I love that it is easily printable from the browser, just CTRL+P.
| adenozine wrote:
| I'm surprised to see mutable default values not mentioned. It's
| bitten me more than once to discover that: def
| f(xs = []): xs.append(5) return xs
| print(f()) print(f())
|
| will print: [5] [5,5]
|
| and I love python despite this horrendous decision, but it should
| be mentioned more often in beginner resources.
|
| edit: thanks for the downvote? I've answered on the order of
| dozens of questions about this very mechanic on SO, via IRC, and
| more... it's a well-known confusing factor
| kubb wrote:
| Don't let it get to you. If you're critical of something,
| someone will always downvote.
|
| On the other hand this behavior means that the default value
| will only get computed once, so I guess Guido thought it's
| useful if that value comes e.g. from an expensive function.
|
| On the other other hand you could achieve that latter behavior
| with a lazy function even if the arguments were reevaluated
| every time you call the function.
|
| What do others like Common Lisp and Ruby do here?
| jinwoo68 wrote:
| In Common Lisp, default values of optional parameters are
| evaluated each time (only when the argument is not given of
| course). They can even reference other arguments that come
| earlier.
| dinkleberg wrote:
| Woah TIL. That does seem like a very strange decision.
| orf wrote:
| Default values for keywords are saved as part of the function
| signature itself, at function definition time.
|
| Without this it's not clear how you'd introspect the default
| kwarg values of a function? Would they be computed every time
| the function is inspected? If they are lazy then what if the
| default value is expensive to compute or has side effects?
|
| So I would not say it's a horrendous decision, it's a clear
| trade off that IMO fits quite well in the Python ethos -
| everything is an object, and everything can be introspected.
| maple3142 wrote:
| It might be confusing as it is different from some other
| languages, such as C++ and JavaScript. They both evaluate
| default parameter when the function are called.
| orf wrote:
| The difference is neither of these can introspect a
| functions arguments at _runtime_. C++ probably doesn't need
| to, as it can do it at compile time with templates, but
| therein lies the difference.
|
| Not to say that it can't is not confusing (at least to
| begin with), but it's not an oversight. It's a conscious
| choice and I think the only safe one you can make.
| tux wrote:
| Very nice detailed cheatsheet thank you! Every programming
| language should have similar cheatsheet.
| gorgoiler wrote:
| _Integral_?
| kubb wrote:
| I'm missing type annotations but I think it's aa cool cheat
| sheet.
|
| These thing are useful for me who uses python every couple of
| months. Not often enough to remember it, so I need some reference
| to refresh my memory.
| runjake wrote:
| I like this.
|
| For those of you for whom this list is too terse, check out the
| excellent LearnXinYminutes site at
| https://learnxinyminutes.com/docs/python/
| mellosouls wrote:
| Great site. Discussed the other day here:
|
| https://news.ycombinator.com/item?id=29518955
| mellosouls wrote:
| To the downvoter(s): yeah I know we shouldn't comment on
| them, but you made me smile at the gesture today, take it
| steady. Merry Xmas!
| hereforphone wrote:
| "For the ages". Or at least until they release Python 4
| hnarn wrote:
| I've seen it said multiple times that it's very likely that
| there will not be a Python 4.
|
| https://www.techrepublic.com/article/programming-languages-w...
| ruph123 wrote:
| The best cheatsheet which I have ever seen (besides maybe
| cheats.rs) is this Python cheatsheet by Laurent Pointal,
| absolutely outstanding in many ways:
|
| https://perso.limsi.fr/pointal/_media/python:cours:mementopy...
| bobnamob wrote:
| Adding to the list, this clojure cheat sheet is always a good
| resource: https://clojure.org/api/cheatsheet
| CodeGlitch wrote:
| It's good, although doesn't mention f-strings, which makes
| string manipulation in python next-level.
| framecowbird wrote:
| There are a couple of language features in Python that I thought
| were cool when I discovered them, but actually have never ever
| find a need for them in my code. The first is using an "else"
| clause in a "for" loop, and the second is returning a value from
| a generator. Curious whether anybody actually uses either of
| those.
| globular-toast wrote:
| for/else is unfortunately named (although makes sense if you
| think about the hidden if/else in a loop). It is essentially
| use to distinguish between "this loop ended naturally" (the
| else condition) or "this loop was broken".
|
| I used it recently in some mutating code in which I wanted to
| make a change, and also know if it did actually make a change.
| If the routine gets to the end of the loop without finding a
| place to make a change, it hits the "else" and returns False.
| CodeGlitch wrote:
| Walrus operator.
|
| I don't think I've seen it in the wild either. Perhaps too new?
| xmcqdpt2 wrote:
| for/else is actually super useful for searching through a
| sequence or for iterating with a possible failure. Something
| like, for i in range(n): if search(i)
| == val: break else: raise
| KeyError("not found") found_index = i
|
| It reduces the need for an additional flag. More importantly it
| makes it easier to ensure that the break condition is satisfied
| such that the loop variable can be used properly later on.
| Personally, I think an else condition should almost always be
| there for loops that gets broken early, similarly to always
| finishing if else chain with a final else.
|
| ETA: Another pattern where it's really useful is to replace
| while True:
|
| with a safer guaranteed terminating loop, for i
| in range(MAX_ITER): ... else: raise
| RuntimeError("exceeded max iterations")
| montebicyclelo wrote:
| What's the advantage over the following?: for
| i in range(n): if search(i) == val:
| break raise KeyError("not found") found_index
| = i
| Arrrlex wrote:
| I think this snippet would raise a KeyError whenever the
| index you're searching for is greater than 0.
| xmcqdpt2 wrote:
| That version doesn't work. It raises KeyError on the first
| iteration if the if statement is false.
|
| The point of the for / else is that the else only gets
| evaluated when the for terminates without a break. So in
| the example you only get a KeyError if the search() never
| returns val.
|
| Part of the confusion I guess is that the else: in my
| example is paired with for, not with if, Python indentation
| being significant etc.
| tjpnz wrote:
| I prefer using the else clause to maintaining an "is_found"
| flag. Although this is lesser known syntax so I probably
| wouldn't use it when multiple developers are involved.
| nneonneo wrote:
| Yeah, the biggest risk with for-else is that some
| inexperienced dev comes along and misreads the else as
| belonging to an if statement inside the for (or, worse,
| attempting to "fix" it). I've seen this happen more than
| once...
| xmcqdpt2 wrote:
| Yes I always comment on it for this reason, sometimes (if I
| know the code will be maintained by someone with less
| python experience) with a link to the standard doc.
|
| It's actually a super useful pattern for any kind of search
| iteration. I've used it many times.
| 63 wrote:
| I actually saw someone use that for-else pattern in advent of
| code earlier this month. I believe the consensus was that it
| was definitely the perfect choice for the given use case, but
| neither he nor I would ever dare use it in production because
| nobody knows about it and it's super unintuitive.
|
| I think the idea is cool (albeit rarely useful), but a
| different word than "else" for the same functionality would go
| a long way.
| nneonneo wrote:
| I used it a bunch in Advent of Code as well. It's very useful
| for "search" loops, which should break on finding the target,
| or do something else if it isn't found.
|
| Generator return, on the other hand, is something I didn't
| even know about (basically, return X in a generator raises
| StopIteration(X)). I don't think it's super useful because
| even inspecting the arguments to an exception tends to be
| uncommon practice in most code I've seen (more frequently,
| you just want to report or suppress the error depending on
| its type). I'm sure there's a niche use for it somewhere
| though!
| globular-toast wrote:
| Instead of avoiding it in production code, it's better to
| understand that it's the perfect place for a comment. For
| example: for ...: ... else:
| # loop ended, no positions found return ...
| dr_kiszonka wrote:
| I find generators useful when working with very large data
| structures because generators can be pretty efficient. You can
| also use them to write little helper functions. Have a look at
| this package and its source [0]. Oh, and don't feel bad if you
| never have a need for generators! For the longest time I felt
| like a steal for rarely using classes but I am over it now :)
|
| 0. https://more-itertools.readthedocs.io/en/stable/
| quietbritishjim wrote:
| They didn't say they hadn't used generators at all. They said
| they hadn't made use of "returning a value from a generator"
| which is different from the usual method of yielding from
| them. def my_generator(): yield
| 1 yield 2 return 3
|
| If you use that generator in a for loop then it will only put
| 1 and 2 into the iterator variable. You have to use the
| generator in a more direct way to get access to the 3.
|
| I haven't made use of return values from generators in my
| code either, but I believe they're used under the hood in
| coroutines in async code.
| anamax wrote:
| I've used both, for with else more often. It avoided some
| booleans and if's that would have been much less clear/easy to
| get wrong.
|
| I'd like a different name for for "for's" else.
|
| I've been using method/function redefinition in place of
| conditionals related to initialization.
| asicsp wrote:
| From Python docs
| (https://docs.python.org/3/tutorial/controlflow.html#break-
| an...):
|
| > _When used with a loop, the else clause has more in common
| with the else clause of a try statement than it does with
| that of if statements: a try statement's else clause runs
| when no exception occurs, and a loop's else clause runs when
| no break occurs._
| AlphaSite wrote:
| It's consistent with try...else and if...else so I actually
| think it's ok.
| 63 wrote:
| "else" usually means "instead of" or "otherwise" in those
| patterns. If the original case doesn't run, then the else
| case runs instead.
|
| In a for loop, the else clause only runs if the loop
| successfully completes (isn't broken), so the else in for-
| else means the total opposite of what it means in every
| other pattern.
|
| I think it would make a lot more sense if it were replaced
| with "done" or "upon" or something else that communicates
| how it works.
| jermy wrote:
| The way you describe is how it worked in zope templates
| (allowing a 'no items here' text if there was nothing to
| iterate over in a list) - it was frustrating that the
| later python implementation was different.
| ptx wrote:
| You could read it as "either process all of these
| elements, or otherwise do this other thing". If we break,
| we're not processing all of the elements (the normal
| case), so we do the "else" part instead.
|
| Edit: This is wrong. See replies.
| 63 wrote:
| That would make total sense if it were correct. That's
| exactly how I think most people would intuit it
|
| However, that's exactly how it doesn't work and that's my
| point. The else clause is only ran if the loop DOESN'T
| break.
| ptx wrote:
| Hmm! Yes, you're right. Even though I knew exactly how it
| works and I sometimes use it, I still got confused, so
| maybe it is a confusing feature after all. :)
___________________________________________________________________
(page generated 2021-12-25 23:02 UTC)