Live data from Hacker News

WTFPython – Understanding Python through surprising snippets

github.com

131–140 of 199 posts

Re: WTFPython – Understanding Python through surprising snippets

#131
post #44

Earlier quoted context omitted.

It’s actually due to python late binding. The variables are looked up at call time, rather than function define time. One could argue that your example shouldn’t work anymore in python3 since variables in list comprehensions go out of scope when they finish now. I haven’t tried it myself. I fill it under, “things I never need to do” :-)

It's not "python late binding", closures behave this way in any language with mutable bindings[0]. The entire point of a closure is to close over its lexical context, if the lexical context is mutable and mutated before the invocation of the closure, the closure is going to reflect that change. for(var i=0; i x^i); } will behave the same way because it does the same thing, so will e.g. for i := 0; i in Go. One of the…

You're right. I remembered the reason after reading your sibling comment and almost deleted my comment to avoid the confusion. Thanks for going into the details.

Re: WTFPython – Understanding Python through surprising snippets

#132
post #8

My biggest complaint about Python is that it somehow doesn’t get flak for having the same (if not worse) scoping as JS, which gets endless hate for its function-scoped variables. (So much so that block scoped variables are the new normal in JS, but not in Py!) Take for instance: >>> powers_of_x = [lambda x: x^i for i in range(10)] >>> [f(2) for f in powers_of_x] [512, 512, 512, 512, 512, 512, 512, 512, 512, 512] To m…

You can achieve the same thing in python by using two lambdas (which is actually what you're doing in JS with map): >>> powers_of_x = [(lambda i: (lambda x: x**i))(i) for i in range(10)] >>> [f(2) for f in powers_of_x] [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] Or you can use default parameter values to use a single lambda (though this means it can be overridden, it's not semantically equivalent to the js implementation…

Parenthetical comprehensions (generator expressions) are equivalent to your expanded function, but list comprehensions are not. `(x for x in range(10))` creates a generator, but using square brackets converts it to a list, including allocating the necessary memory. If you’re trying to do yield and streaming, the parens will serve you better.

Re: WTFPython – Understanding Python through surprising snippets

#133
post #100

Earlier quoted context omitted.

I don’t think you’ve actually understood my proposal, and the snide remarks about completely unrelated languages don’t help your argument. To reiterate, my proposal is that the walrus operator has the exact same semantics as the assignment operator, but creates an expression rather than a statement. A linter rule could then be added prohibits the assignment operator, and converts all instances of it to the walrus ope…

> and the snide remarks about completely unrelated languages don’t help your argument. Granted, I apologize. It was childish. > but creates an expression rather than a statement. Expressions are limited in Python for the same reasons. It's the same rational that got us tone done lambdas. People code with a certain style using it, which is not the style we want to promote for Python. > A linter rule could then be adde…

> yet ignore the fact that the actual creator of the language was so against the addition of this operator that he saw the community’s insistence on it as reason to step down as BDFL.

Regarding this part, Guido specifically addressed the toxic debate as the reason for stepping down as BDFL, and not the operator per se.

(Yes, I'm reinforcing BiteCode_dev's reply on this point)

Re: WTFPython – Understanding Python through surprising snippets

#134
post #115

Earlier quoted context omitted.

Encoding strings internally as UTF-8 is a fine idea, usually you don't need constant-time access to individual code points. E.g. PyPy (faster Python, with JIT) does so. Many other languages also save strings as UTF-8.

And then you have to either re-train them to use string cursors or you have lots of people writing inefficient string code.

Not really, no. PyPy demonstrates that.

Re: WTFPython – Understanding Python through surprising snippets

#135
post #108

Earlier quoted context omitted.

> the actual creator of the language was so against the addition of this operator that he saw the community’s insistence on it as reason to step down as BDFL. That's backwards. The community was generally opposed to the walrus operator, and Guido stepped down because of (among other things) the community's reaction when he insisted on adding it.

Oh interesting. I’m with the community on this one.

I'm on Guidos side. When it's well used, it's a good thing -- problem is getting people to use it right. But the fact that many people didn't consider the use cases that were being proposed, immediately took strong and toxic positions about it, and were more interested in calling names rather than having a civilized discussion is what wore down the (then) BDFL and caused him to step down.

Re: WTFPython – Understanding Python through surprising snippets

#136
post #44

Earlier quoted context omitted.

It’s actually due to python late binding. The variables are looked up at call time, rather than function define time. One could argue that your example shouldn’t work anymore in python3 since variables in list comprehensions go out of scope when they finish now. I haven’t tried it myself. I fill it under, “things I never need to do” :-)

It's not "python late binding", closures behave this way in any language with mutable bindings[0]. The entire point of a closure is to close over its lexical context, if the lexical context is mutable and mutated before the invocation of the closure, the closure is going to reflect that change. for(var i=0; i x^i); } will behave the same way because it does the same thing, so will e.g. for i := 0; i in Go. One of the…

Works intuitively in golang:

https://play.golang.org/p/pn2jBTaTNS8

  package main
  
  import (
   "fmt"
  )
  
  // return a^n
  func Power(a, n int) int {
   var i, result int
   result = 1
   for i = 0; i 

Re: WTFPython – Understanding Python through surprising snippets

#137
post #55

It's a good repo, but remember a lot of those are "A Good Thing™". The first snippet is a very good example: a := "wtf_walrus" doesn't work while: (a := "wtf_walrus") works. It's a fantastic design decision. Python took a long time before getting this operator, because it's a language that favors being readable, easy to use, and above all, to learn. But in many other languages, the very same operator is often misused…

in the zen of python (import this) it says: there should be one-- and preferably only one --obvious way to do it. sadly this is not true for a while in python now. Python became a language that can be really hard to read now.

As a relative newcomer to Python (compared to most, but I do use it professionally every working day for a year, and some non-working days for personal stuff), I find this to be the case. At work I have to use Django, and it's almost a chore to find anything explicit or obvious in it. Its level of abstraction is "Too Damn High" as the meme goes, IMO.

It feels like saving boilerplate for the sake of it which just makes obvious, readable code into magic incantations where shit happens and you don't know why or how or where to look.

Re: WTFPython – Understanding Python through surprising snippets

#138
post #36

If only it had curly braces instead of just indention. God, that kills me. And used unicode instead of ascii as the default. And there wasn't python 2.7 vs 3. Someone help me stop this list.

When you write in a language which uses curly braces for statement grouping, do you indent your code? ...? I thought so.

Generally not; emacs or VSCode or IntelliJ or whatever does for me.

Does for python, too.

Re: WTFPython – Understanding Python through surprising snippets

#139

It's interesting to see the walrus operator in there. I wonder, is this another example of unnecessary features being added just to claim a bigger change list, or someone really needs this operator? Why would anyone prefer a walrus instead of adding just one more line to their code, which also helps with readability?

Coming from Mathematica to Python, the lack of a assignment expressions yet inclusion of list comprehensions felt like a severe crippling of the language feature. Sure you “can still do the same through other means”, just like if, for and while are all unnecessary syntactic sugar in every language. But the thing is that list comprehensions provide a nice obvious concise way to frame your solution, but if you use it without assignment expressions you often end up repeating computations unnecessarily.

Re: WTFPython – Understanding Python through surprising snippets

#140
post #45

Earlier quoted context omitted.

A while ago, I was also sceptical about the walrus operator, although I use assignments in expressions all the time in C++. But when I was perusing a library written Python the other day, I found five spots in which the walrus operator would make sense - eliminating one line of source code without readability suffering from it.

Is saving 5 lines of code really worth breaking Python's "one way to do it" design principle?

[deleted]
Post reply on HN