[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)