Live data from Hacker News

A Python Guide for the Ages

gto76.github.io

51–59 of 59 posts

Re: A Python Guide for the Ages

#51

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.

Walrus operator. I don't think I've seen it in the wild either. Perhaps too new?

It’s used a lot in simple situations. However never seen it used for multiple values, which was the reason given for using := instead of the “as” keyword used elsewhere. So I cringe every time I use it.

Re: A Python Guide for the Ages

#52
post #44

"For the ages". Or at least until they release Python 4

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...

That was a joke about Python 3.

Re: A Python Guide for the Ages

#53
post #6

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...

It's good, although doesn't mention f-strings, which makes string manipulation in python next-level.

Yeah, unfortunately it hasn't been updated in a few years. Real bummer.

Re: A Python Guide for the Ages

#54

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…

Use a linter. Almost all of them warn about this footgun.

Re: A Python Guide for the Ages

#55

Earlier quoted context omitted.

What's the advantage over the following?: for i in range(n): if search(i) == val: break raise KeyError("not found") found_index = i

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.

[deleted]

Re: A Python Guide for the Ages

#56

Earlier quoted context omitted.

What's the advantage over the following?: for i in range(n): if search(i) == val: break raise KeyError("not found") found_index = i

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.

Aha, thank you. Yes, it's plausible that my brain did pair the `else` with the `if`, even though it knew it was supposed to be paired with the `for`.

Before being introduced to `for`/`else`, I'd have written the example you gave as:

  result = None
  for i in range(n):
      if search(i) == val:
          result = i
  if not result:
      raise KeyError("not found")

Re: A Python Guide for the Ages

#57
post #9

Earlier quoted context omitted.

It’s consistent with try…else and if…else so I actually think it’s ok.

"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…

It depends on whether you think of the break as success or failure. When I write a loop with a break it's usually some kind of search where the break happens once you've found something, and in that case the break is more of a success.

Re: A Python Guide for the Ages

#58

Earlier quoted context omitted.

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/stab…

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…

I used generators with return values once when writing a lexer. I had generators for each of a bunch of different states of the lexer (e.g. skipping over whitespace, reading a numeric literal, reading a string literal, etc.). Each generator would yielded the tokens that it could and then either return one of the other generators (if a state transition was required) or None (if it reached the end of the input and the state was one where this wasn't an error condition). The whole thing was tied together with this function:

  def lex(src):
    state = skip_whitespace

    while state is not None:
      state = yield from state()
It wasn't particularly essential to use the return value from the generator here, as I could have just made the state variable available in the scope of the state functions for them to mutate, but this seemed like a cleaner way to do it as it enforced the idea that each new state corresponded to a new function.

Re: A Python Guide for the Ages

#59
post #7

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.

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.

Raymond Hettinger has a good section on this, tracing it back Knuth's discourse on structured programming in the face of 'goto'. He suggests calling the keyword 'nobreak', rather than 'else'.

Inside any loop are a conditional and a jump. In pseudocode:

    if not  then
        
        
    else //loop is done
        
If we 'break' in the body of the loop for some reason, we will never hit the 'else' in this chunk of code. As Mr. Hettinger explains, this is obvious to anyone reading Knuth or coming from a 'goto' style of control flow. This is not an insult, but an observation. (Un)Fortunately, structured programming is the absolute norm now, and we learn looping constructs directly, rather than learning 'goto' and then building to looping constructs. Especially in a language with rich iteration protocols, such as Python, it is very much unapparent that the looping constructs are fancy wrappers around 'goto'.

Link to the talk: https://youtu.be/OSGv2VnC0go?t=948

Post reply on HN