One of the most informative books I read early in my career was "C traps and pitfalls". I've written a lot of C in the subsequent 20 years or so. It has some particularly nasty traps. Acknowledging that does not make me anti-C.
Pointing out that a saw is sharp does not make you anti-saw.
depends on your cultural background I guess. Some people see literally everything that is not 100% risk-free as inherently bad.
I mean... yes. That's, like, most people.
If we can achieve a N% risk-free Python (without sacrificing other useful features), and we only have a M% risk-free Python (where M < N, or even M << N), then what we have is inherently bad.
Not speaking for the quality of the article, but on that sentiment: maybe it's just that the pro-python sentiment is eroding. I'm glad it's becoming kind of ok to criticise that language, after years of it being untouchable (at its core, not the 2 -> 3 migration). At least that's my sentiment as someone who really doesn't like it (but I'm a professional, I still use it when it's a best tool for the job, it's just a pain). I'm sure just saying that is still suspicious, and saying that I prefer JS (modern) to Python will still get me more than raised eyebrows for at least a few more years.
I've only been following Python for a little over 20 years of it's ~30 year life, but I don't remember it ever being “untouchable”, or even just “untouched” by criticism.
Edit: the XKCD antigravity comic was December 2007, so pretty early on all things considered. PG’s Python Paradox was 2004.
When Python became popular in education, particularly for first CS courses, is when the public criticism from Scheme, Java, and and C partisans really skyrocketed.
Yeah, it has had recently a generally good reputation. That doesn't mean that it has been untouchable and immune to criticism.
You'd be surprised. Python was used quite a lot in early 00s.
Ruby is the one that was a curiosity few used at that point, until Rails came.
I suspect that the reason that it's so common to be initially suspected of being an ideologue is that there are so many out there, and they are very vocal compared to the majority that often couldn't care less. So if you don't come up with alternate solutions, maybe the tendency is to assume you're getting at the old trope they've already heard before.
As if wishing for any performance that’s an improvement on bottom-of-the-barrel is some kind of wild, unreasonable ask for which the solution is “write it in a language full of pitfalls, sharp edges and an even worse packaging and developer experience than the current one? Seriously?
LOL. JS is what, 25 years old, versus Python at 30.
Despite the name, I don't think this is anti-python, in the same way classics like [0] are anti-PHP. The project README mentions this a bit:
> While some of the examples you see below may not be WTFs in the truest sense, but they'll reveal some of the interesting parts of Python that you might be unaware of. I find it a nice way to learn the internals of a programming language, and I believe that you'll find it interesting too!
0: https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/
Of course once you get more deeply into a language it's probably a really good thing to get to know all the weird edge cases. One of my favorite past-times is writing intentionally terrible code just to exercise some of those edge cases. For instance this hello world code uses quite some oddball language features: https://gist.github.com/SuperDoxin/fde4fdad237e85a90c8764cdf...
Once you're getting better at the language it's nice to know these edge cases because they teach you details about the language you'd otherwise miss out on.
Yes, it is in fact extremely surprising that an expression does something different based on surrounding context. It would be as if expr had one meaning but it you called f(expr) it had another. Saying that you're using it unexpectedly doesn't really address the issue of language design.
It reminds me of Matlab's idea (a long time ago) that f(i) is either a function call or an array access at index i, but you will not know for sure until you've evaluated f, so expressions like f(i)(j) end up being just weird. There is a certain amount of logic that you are fully justified in expecting from a language.
> It's not what that operator is for.
If your idea is that an operator is free to do whatever, once it's outside its predicted situation, then I can see how that's technically correct based on the language spec, but it just seems like a very weird way to just a language design.
I think if you think that some of those examples have no legitimate uses at all you'd then have no problem saying that they should be syntax errors but are accepted anyway, that it's just a bug in the parser, that it accepts too much.
I also do not see how this is anti-python, I think you are being unfair to the author.
It isn't doing anything different though. Compare:
>>> a:=1
1
>>> (1, 2)
(1, 2)
>>> (a:=1, 2)
(1, 2)
The thing that's confusing people here isn't even the walrus operator, it's tuple syntax.> If your idea is that an operator is free to do whatever, once it's outside its predicted situation
No it's not. But clearly an operator can never do an operation it isn't defined to do. is and == are different operators and they do different things.
> I think if you think that some of those examples have no legitimate uses at all
They do have legitimate uses, but purposefully obfuscating the context around what the code is doing is hardly the fault of the language.
> I also do not see how this is anti-python, I think you are being unfair to the author.
Yeah on further thought it really isn't anti-python, but articles like the OP do tend to get linked in anti-language posts, which is probably what got me a bit annoyed about the article. No fault of the author.
Except the string comparison with "is". It's confusing, because there are no errors, and when I try them in the Python REPL, it "works". The code is logical, I tested the example and it works...
...except when it doesn't, but if I'm just a naive beginner, I'll need to learn the hard way that it doesn't always work
For this reason, I'd be okay with saying that "it" for strings is a WTF of the language.
In other words:
x = "foo"
y = "foo"
x == y and x is y
Both strings point to the same exact memory. Hence, 'is' works.
But it isn't always true: x = "foo"
y = f"{x} "[:-1] # get everything but the space
x == y # True
y is x # FalseEvery JVM language that came after Java reverses this. Here, "is" simply is too nice. Should've named it something nobody will accidentally use.
In python it’s common due to `None`, which you really want to check by identity. Other placeholders as well. This is such a major use case that in 3.9 `is` was moved out of the generic `compare_op` instruction and into its own.
And because __eq__ can be overridden, aside from being noticeably slower `x == None` is not truly reliable.
Rule of thumb is use == for everything except True/False/None. Once you get going with python you'll learn the meaning of is eventually, and you'll still barely ever need to use it.
Small integers, as they are kept around, probably are as well (5 is (2+3) works).
I think what gets dropped during the conversation is, that we've been living with Java doing it this way (is being == and == being .equals) for decades and nobody really complains.
2. 1 == True and 0 == False, as booleans subclass the int type. On the other hand is distingushes between 1 and True, and 0 and False respectively.
I can’t think of any popular language that doesn’t have weird quirks.
That said, the content of the post is useful. Knowing about this behaviour, even when it’s demonstrated by using language features incorrectly, is important. I’ve seen enough code that misuses “is” on strings to know there’s a need for information like this to be collated and accessible.
>> none of the code on this page is something anyone would actually write in production code on purpose.
I mostly agree, but there is one example where I thought it is important to know and remember:for x in range(7): def some_func(): return x
Here x binds to the (outside) symbol x, not the value of x at creation time of the inner function.
I've seen the same, but to me it feels like the downslope of the hype-train that was brought on by the ML crowd. Early on there was python doing python things, and the (IMO overly smug) community was happy with that. Then the AI/ML hype train fired up and for historical #reasons python became the language of choice, and this introduced a LOT more people to the language, and it became their lingua franca.
Now, those people are having to write honest to god applications and are finding that python is Hard To Scale, both technically and code-management-y.
IMO. Reasonable people disagree.
It's kind of like saying that AMD processors or Microsoft Word are hard to scale - it's not entirely meaningless as a criticism but it's close to it.
Python is not a language for writing ultraperformant multi threaded code but, of course, that's not what it used for or was ever intended to do and is an entirely separate issue to scalability.
Reasonable people disagree about well defined, important matters.
It is odd that you would say that, because it is a very common complaint about languages with dynamic typing. As the program grows larger static typechecking becomes more and more helpful.
Regardless, python has tools to do that. Instagram and Dropbox in particular have written quite a lot about their internal usage and built and open sourced additional tooling (e.g. MonkeyType - that lets your code type annotate itself).
How about organizations that hit the scaling point, but are not big enough to invest into tooling like that?
It's exactly the kind of tooling that makes your life easier if you have multiple teams and wanted to start enforcing static type checks with MyPy and having an IDE that understood your types.
So before Python had types was it hard to scale or not?
Seems like you are defending "Python with types and lots of tooling" rather than Python "nice and simple language (until not)".
Main difference is that the python community has a rather strong reaction to how pythonic your code is. You'll notice soon enough after working with python that for most python developers "it works" isn't good enough reason for anything. It has to work and fit how you're supposed to write python.
Some of it is encoded in style guides like pep8, but most of it is pretty hard to codify like that.
If you're familiar with C, id() returns the memory address of the thing given to it, and "x is y" is like "id(x) == id(y)". So "x" is "x" is asking whether the Python runtime happened to put the two strings in the same place in memory, not whether the two strings are equal.
("is" is commonly used for one thing - testing against None. So you might write "a is None". I think that's just because someone once got bitten by a badly overloaded == operator. Just like some people will write === in all their Javascript, in case an incorrect type sneaks in.)
Edge cases are really interesting. It's important to know them, and it's no comment on the language.
The same happened to Ruby and Rails. Once the last "in" thing no longer gets attention and new "in" things are the talk of the blogosphere, "yesterday's" things start to get dissed.
I think it's to gain points for recognizing the new thing. To attract people following "old" thing to the "new" thing and provide social validation or increased mindshare for one's choices.
Or maybe people are tired of pain points with the old way (even if just perceived or tangentially related), and they need to lash out at something.
Yes doing the walrus operator inside brackets works. Yes of course it's going to be doing weird things. Is this really surprising to anyone? It's not what that operator is for.
Yes comparing strings with "is" works sometimes. It's not checking equality and it isn't supposed to. In another implementation using "is" might work all the time or none of the time. Don't use "is" to compare strings. it's not what that's for.
Yes chaining mismatching operations does weird things. Be clearer in how you write your code. It's no surprise that writing confusing code results in confusing results.
I've been seeing a growing anti-python sentiment lately, and most of it seems to be based on these sorts of odd perceived language defects. Python is by no means perfect, but none of the code on this page is something anyone would actually write in production code on purpose.
I suppose it's a sign of python getting more popular.