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…
A contrarian's point of view: > The very same operator is often misused as, or confused for, the operator for equality or assignation. It will still be confused, I'm afraid. It's just a little less likely that that confusion will be silently accepted by the interpreter. > Also to hint people at using it only when necessary. Let's be clear: the walrus operator was never, ever, necessary. It's syntactic sugar to avoid…
WTFPython – Understanding Python through surprising snippets
171–180 of 199 posts
Re: WTFPython – Understanding Python through surprising snippets
#172Earlier quoted context omitted.
It uses unicode but it doesn’t use UTF-8 by default as external encoding and never as internal encoding except for an optional secondary buffer.
What do you mean by "external encoding", "internal encoding", "secondary buffer"?
Internal encoding: what the strings are encoded in memory (latin1/UCS2/UCS4 in python)
Secondary buffer: python strings can be encoded twice. They can hold a secondary encoded version if themselves as utf-8.
Re: WTFPython – Understanding Python through surprising snippets
#173Earlier quoted context omitted.
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 make…
If you've ever taken a look at something like Flask or Cherrypi, the difference is very apparent.
That said, I've been doing some Rails lately, after years of Django, and I'm finding the experience to be worse from a readability point of view. Metaprogramming everywhere, modifications of language constructs ... It gets very confusing very quickly. Could be simply a lack of experience of course.
In parallel, I've also been using Go and the experience could not be any different. So much easier to understand what is going on, but so much boilerplate code!
It doesn't look like it's possible to have both ease of use and explicitness...
Re: WTFPython – Understanding Python through surprising snippets
#174Earlier quoted context omitted.
The many, many ways to print variables inside of a string are testament to that. I remember feeling kind of a chill when the number of methods hit three. Two is an acceptable number of methods if you are transitioning from one form to another as kind of a nod to the growing pains of a language, but at three you have hit some kind of watershed.
There's actually five now! 1. manual string concatenation 2. the old, printf-style. Still heavily used in e.g. stdlib logging module. 3. .format() 4. f-strings 5. string.Template in the stdlib Yup, I definitely see this as one of the bigger failures in Python's design.
Even in the p3 transition, the community screamed to not remove them. Did you know we removed % for a few versiond ? We had to put it back because of all the complaints.
Re: WTFPython – Understanding Python through surprising snippets
#175Earlier quoted context omitted.
The many, many ways to print variables inside of a string are testament to that. I remember feeling kind of a chill when the number of methods hit three. Two is an acceptable number of methods if you are transitioning from one form to another as kind of a nod to the growing pains of a language, but at three you have hit some kind of watershed.
There's actually five now! 1. manual string concatenation 2. the old, printf-style. Still heavily used in e.g. stdlib logging module. 3. .format() 4. f-strings 5. string.Template in the stdlib Yup, I definitely see this as one of the bigger failures in Python's design.
Re: WTFPython – Understanding Python through surprising snippets
#176Earlier quoted context omitted.
All it does is produce an error: "UnboundLocalError: local variable 'a' referenced before assignment". The second f() call makes no difference.
Is that what you expected from such a simple piece of code?
Re: WTFPython – Understanding Python through surprising snippets
#177Earlier quoted context omitted.
Is that what you expected from such a simple piece of code?
Well it's f that has the problem, rather obviously, and the other three lines are unrelated. So I don't see how this is some especially simple way of triggering that error.
a = 0
def f():
print(a)
f()
Maybe this is all obvious to you, but I'll bet you can't name any other language which behaves this way. Compare the original Python to JavaScript (or Lua, Perl, Tcl, Ruby, C, Scheme, Rust, Clojure, or ...): a = 0
function f() {
console.log(a)
a = 1
}
f()
f()
This one behaves how I think most people would initially expect the Python snippet to behave. First it prints 0, then it prints 1. (Of course JavaScript has it's flaws too...) If you don't believe me, ask your coworkers and friends what they think it does before running it.My only real point is that Python conflates variable declaration and variable assignment in a way which initially seems like a friendly time-saver, but which ends up being pretty subtle and confusing until you've learned its quirks. All of that just to avoid declaring your variables (in some fictional version of Python):
var a = 0
def f():
print(a)
a = 1
f()
f()
Here it would be clear which are declarations + initializations, and which are only assignments. And for just the cost of typing the word "var", the compiler could tell you when you've made typos in your variable names. As an added bonus, you could get rid of the "global" and "nonlocal" keywords.Re: WTFPython – Understanding Python through surprising snippets
#178My 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…
This situation is mentioned in the docs: https://docs.python.org/3.8/faq/programming.html#why-do-lamb... "This happens because i is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called — not when it is defined. At the end of the loop, the value of i is 4, so all the functions now return 4 2, i.e. 16." These sort of scoping gotchas are pretty common across all progr…
Re: WTFPython – Understanding Python through surprising snippets
#179Earlier quoted context omitted.
Well it's f that has the problem, rather obviously, and the other three lines are unrelated. So I don't see how this is some especially simple way of triggering that error.
The other three lines are not unrelated. If you just take the first three lies (and the last one), it's fine: a = 0 def f(): print(a) f() Maybe this is all obvious to you, but I'll bet you can't name any other language which behaves this way. Compare the original Python to JavaScript (or Lua, Perl, Tcl, Ruby, C, Scheme, Rust, Clojure, or ...): a = 0 function f() { console.log(a) a = 1 } f() f() This one behaves how I…
var a = 9;
function foo() {
console.log(a);
var a = 12;
}
foo();
$node foo.js
undefined
The same goes with ruby.Re: WTFPython – Understanding Python through surprising snippets
#180Earlier quoted context omitted.
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.