Skip to content(if available)orjump to list(if available)

What the Fuck Python

What the Fuck Python

146 comments

·July 19, 2025

pansa2

My favourite Python misfeature is that `x += y` sometimes does the same thing as `x = x + y` and sometimes doesn't. This leads to minor WTFs like this:

  >>> a = b = (1, 2)        >>> a = b = (1, 2)
  >>> a = a + (3, 4)        >>> a += (3, 4)
  >>> b                     >>> b
  (1, 2)                    (1, 2)

  >>> a = b = [1, 2]        >>> a = b = [1, 2]
  >>> a = a + [3, 4]        >>> a += [3, 4]
  >>> b                     >>> b
  [1, 2]                    [1, 2, 3, 4]
And major ones like this:

  >>> a = ([1, 2], ['one', 'two'])
  >>> a[0] += [3, 4]
  TypeError: 'tuple' object does not support item assignment
  >>> a
  ([1, 2, 3, 4], ['one', 'two'])
The operation raises an exception even though it succeeds!

harrisi

I'm surprised by the reactions to this. It's made immediately clear in the notebook that this is a fun look at some interesting behaviors of Python. There's no implication that there are bugs - I have no idea where anyone got that idea - except for the single actual bug in CPython that is mentioned (https://github.com/python/cpython/issues/54753).

I don't feel strongly about Python, but I do think CPython is a great way for people to learn a bit about how interpreted languages work. The code is quite easy to understand, and you can easily play with these interesting aspects of how languages and runtimes work. Does every Python programmer need to know the difference between `a = 256` and `a = 257`? No. Is it interesting? Yes. Should someone on your team know? Probably.

There's a lot of interesting stuff here. Understanding the difference between the conceptual idea of each line of code and what actually happens is fun, and, in some cases, important.

msgodel

It probably wasn't a good idea to start it out is showing string constants aren't optimized. If they wanted to talk about really unintuitive reference gotchas initialization in optional function parameters would have been a way better example.

harrisi

I appreciate the sentiment, but even this is a good example of why this stuff is interesting. Because some strings _are_ optimized (using some definition of "optimized"), but only in some cases.

It's these quirky little things where the code doesn't exactly represent the way execution happens in most straightforward mental models of how execution works. Again, it's not bad and it's not unique to Python. It's just the nitty gritty of how some things work.

I will say that calling it "What The Fuck Python" is certainly more attention-grabbing than "Some Interesting Bits About Python Internals You Probably Don't Need To Know". What're you gonna do. :)

kazinator

Bad requirements are bugs.

Bugs in understanding. Bugs in good taste.

A roach in your soup is a bug, even if the recipe says it should be there.

hansvm

The first third of this seems to just be complaining that it's not obvious when two objects are actually the same object, and that if you mistake identity-related operators for other operators then you'll have a bad day.

That's a fair critique. It's a little weird that `is` and friends have dedicated, short, nice syntax.

On the other hand, most compiled languages are compatible with an implementation which admits the following optimization:

  const a: u32 = 42;
  const b: u32 = 42;
  assert(&a == &b);
The language usually doesn't guarantee that different immutable variables have dedicated memory on the stack, or that they even live on the stack in the first place.

That's the same class of error we're seeing here, and even among popular interpreted languages Python is by no means unique. I might get to the bottom 2/3 of the doc later, but the rest was off-putting enough that I don't know I'll bother.

hmry

Yeah, it would be much clearer if instead of an `a is b` operator, there was a `same_object(a, b)` built-in method.

bb88

It doesn't matter much since pointers are never comparable in python, just values.

alabhyajindal

Preach. We need more Python slander. It annoys me to no end when people trash JavaScript as if it was some exception in bad language design. Most languages have something bad that can be picked up and trashed on - some more than others.

bnchrch

Thank you! For years Ive been saying the sheer volume and fury by which Javascript is criticized is much more applicable to Python.

Both aren't perfect languages, and both are far from "the best" but it is maddening that Python get often picked as a darling when its implementation, ecosystem and tooling are fundamentally at odds with correctness and productivity.

verbify

I think people pick on js more because it's the only option for scripting frontend for the web, while if you don't like python there's probably another language that can be used instead.

dreamcompiler

Unless you're doing AI, in which case you're royally screwed.

hamstergene

There could be generational gap here: for many people the first JS was ES5 or later, which is after the language was taken seriously and fixed. The difference between Python2 and ES1-ES3 was much bigger than between modern Python and modern JavaScript, so some protest against old bad fame is understandable.

But, if you have any suspicion that JavaScript has been treated unfairly: it hasn't. It is literally being replaced by TypeScript as we speak. The fact you have to invite people to come up with more Python slander is itself a testimony, JavaScript has never needed an invitation. Having lot more issues than others is what being exception means, and JavaScript is one.

motorest

> We need more Python slander. It annoys me to no end when people trash JavaScript as if it was some exception in bad language design.

Python's file system support across platforms is notoriously problematic or even outright broken. Wasn't this enough reason to put it lower in the quality bar than JavaScript?

akdor1154

JavaScript doesn’t even have file system support.. each runtime has its own tacked on implementation in the relevant “standard” library. Now which is notoriously problematic?

bb88

How does this attract more people to hackernews who come from the python world? If anything, it just shows how toxic people can be on this site.

throwaway314155

JavaScript is far more jarring than Python depending on your background. They do both have issues of course, but that's the reason JavaScript gets "picked on" more.

fragmede

bb88

I came here to say that. That was an eye opening intro to Javascript for me.

heavenlyblue

Given that it starts with a thing called "id" which is an implementation detail and probably should not be used for equality, it seems like this is a geniuinely well designed language :)

mirashii

id is not an implementation detail, it's a core built-in function of the language. The value that it returns is an implementation detail, but the properties of the value it returns are not and perfectly valid to rely on.

zahlman

`id()` is documented and mandated to exist, and the result provides guarantees that make it suitable for identity (not equality) checks[1] (although of course you should normally use the `is` operator). Pitfalls involving it are generally really pitfalls with understanding object lifetimes[2].

[1]: https://docs.python.org/3/library/functions.html#id

[2]: see e.g. https://stackoverflow.com/questions/52096582

moffkalast

Yeah python deserves a good bashing as well, it's about as bad as JS in this regard. I mean for bool("false") resolves to True ffs.

3eb7988a1663

That is entirely consistent with how truthiness works in Python. The function does not claim to parse strings, that is how you get YAML Norway.

Do you think there should be different results for bool("no"), bool("false"), bool("heckno!"), bool("heckyes!")?

Edit: should have included internationalization: bool("nein!")

crazygringo

> The function does not claim to parse strings

But it's entirely reasonable to think it would. I honestly don't understand why it wouldn't, because:

  >>> int("35")
  35
  >>> float("3.5")
  3.5
  >>> bool("False")
  True
If casting from a string to a type works with ints and floats, why not with bools? What possible justification is there?

And of course it doesn't need to work for "no" or "heckno!", that's silly. But it sure seems like it ought to work on whatever the official string representation is. And not produce:

  >>> bool(str(False))
  True
I'd honestly much prefer bool() threw an exception on receiving a string, rather than act the way it does now.

moffkalast

Honestly once you really think about it just about nothing about these decisions ever makes any real sense which is why JS is made fun of constantly. It's nonsense functions running on nonsense data. "if some_non_bool_value:" should not be valid syntax and truthy and falsy is a concept that would get you locked up in an asylum if you decided to explain it to a doctor.

bnchrch

Don't forget its transitive dependencies creating non-deterministic builds

librasteve

yeah

in raku, i checked

  say False.so; #False

Jtsummers

If I understand raku correctly, the Python example would be more like this:

  say "False".Bool
or:

  say "False".so
Both of which display True.

Leaving out the quotes means you're testing something else entirely.

Note that the Python example is converting (via `bool`) a string with the text "false" (which would make more sense as "False" which is the actual name of `False` in Python) into a boolean value. It's consistent with how Python behaves, in that the empty string (like in Raku from what I can tell) is false-y and non-empty strings are truth-y. It would be weird to have this use the else branch:

  if bool("False"):
    ...
  else:
    ...
But not this:

  if "False":
    ...
  else:
    ...

Danjoe4

Who writes python this way? Good Python code, being such a flexible language, relies on conventions. Never seen the id() function in production code. "Is" is canonically used for "if var is None", not string comparisons. Python has a rich library of string methods, maybe use them?

You're finding bugs because you're using the language like a QA tester instead of the way its intended. If I saw string_var is "some_string" in a PR, I would reject it. Even the triple boolean comparison example should just be separated with an "and".

Read PEP20 and PEP8. A goal of Python is to be as readable as possible, not to conform to some spec. You may not agree with that design decision, but all these examples have an obviously more readable alternative which would work.

Jeez. It's like me complaining that Rust looks ugly (it does). The language was designed with a different set of priorities.

duncanfwalker

I mainly see this wtf pages as a hook to talk about the internals of a language/interpretor/etc. As you say, there's no point reading them as a criticism of the language because that's just not what production python looks like. I read the line of code and think 'can I imagine why it does that?' if I can I skip the explanation but sometimes I have absolutely no idea what's going on and they're the ones I like to read the detail on

crazygringo

> A goal of Python is to be as readable as possible, not to conform to some spec.

The goal of every programming language should be to conform to a spec that is as logical and consistent as possible. This prevents bugs by saving tons of mental effort having to worry about and look up edge cases, and not always catching them all.

I don't mind so much if end-user applications have bugs when they're used differently from intended, because their use cases are narrow. If Word crashes when I put 10,000 images on a single page, well obviously it's not built for that.

But I mind very much when programming languages have bugs, because they are the layer on top of which we build so many other things! The use cases for a programming language are almost infinitely wide.

For a language as widely used as Python, we should be testing it out like QA testers. All these inconsistencies add up to tons of bugs when you expect something to follow a consistent pattern and it doesn't.

evertedsphere

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

the spirit in which that page is presented is different from what you seem to have taken it to mean

motorest

> You're finding bugs because you're using the language like a QA tester instead of the way its intended.

What do you think this means? Are the bugs there or not?

FreakLegion

Which ones are bugs? I read the first few sections and glanced through the rest, but it's a long notebook. There were runtime-specific implementation details, operator precedence, genuine language footguns (like scoping rules), but no bugs that I saw.

fragmede

Not all bugs are equal though, and if I'm only going to run across the bug when I'm standing on my head the third Wednesday of the month while singing Poker Face, it's a bit less concerning than one that happens only on days that end in "Y".

happytoexplain

So we shouldn't learn about them? They're offensive to enumerate? No, they're useful to understand.

motorest

I think you're showing some despair in trying to avoid addressing the fact that there are indeed bugs. There is nothing suggesting bugs are obscure or random. You have a list of examples. Is it hard to acknowledge the problems are there? What exactly makes you feel threatened or personally attacked by a bug tracker?

coldtea

You seem to have missed the entire purpose of the post.

It's not to give "best practices" but to unveil gotchas and peculiarities in the language implementation and internals.

>A goal of Python is to be as readable as possible, not to conform to some spec.

This doesn't even make sense.

pyuser583

“Is” checks memory location of the values.

sundarurfriend

> Who writes python this way?

People learning the language or learning programming, something Python is supposed to be good for and is widely used for. Also, casual and intermittent users of Python, who might not hold all the details in their head because they work in multiple different languages. These categories would encapsulate the majority of Python users in practice, and all of them end up "QA testing" the language unintentionally and wasting time and effort figuring out inscrutable problems.

A better designed language could prevent a lot of these abuses, give informative error messages, or at the least warnings. These are not inevitable results of language flexibility, but in many cases just the result of poor design that got patched up imperfectly over time - which is understandable given Python's history, but doesn't make the problems go away.

happytoexplain

Why are you being so defensive? Every language has bad or surprising (which IMHO is a synonym for bad) design choices. These are just a few of Python's. "You're using it wrong" seems like an unrelated criticism. Languages have the luxury of dictating how you use them.

LPisGood

Some of these just seem to be using Python out of spec and being surprised that implementation details exist, and misunderstanding boolean expressions.

otabdeveloper4

Python doesn't have a spec. It barely even has documentation nowadays. (Sad. Twenty five years ago it was the gold standard of documenting software.)

zahlman

Python's documentation today[1] is clearly more expansive, better formatted and more readily comprehensible than its documentation from 2001[2] (or even 2008[3]). There are multiple entire sections of documentation now that didn't exist before. Standards were just lower back then, partly because a larger percentage of "programmers" were accustomed to wrestling with beasts like C, and partly because systems were much smaller.

https://docs.python.org/3/

https://docs.python.org/2.0/

https://docs.python.org/2.5/

motorest

> Python's documentation today[1] is clearly more expansive, better formatted and more readily comprehensible than its documentation from 2001[2] (or even 2008[3]).

Documentation is not a specification. Specifications cover all behavior that should be expected, and specify which behavior is implementation-defined or undefined. If something isn't defined them this is a failure in the specification that requires fixing. The point of a specification is to allow independent parties to do clean room implementations that can be used interchangeably.

otabdeveloper4

Good documentation cannot be "expansive". Good documentation must be a) thorough and b) minimal.

Modern Python documentation is absolutely horrible - there's a shitload of irrelevant rambling while absolutely crucial details are omitted.

simonw

https://docs.python.org/3/reference/grammar.html and https://docs.python.org/3/reference/index.html look pretty comprehensive to me, and they're backed up by a thorough collection of PEPs: https://peps.python.org/pep-0000/

As a relatively recent example, here's the language reference documentation for the match statement https://docs.python.org/3/reference/compound_stmts.html#the-...

LPisGood

I don’t understand what you mean by “doesn’t have a spec”

The existence of Pypy and CPython and separate but compatible entities shows that there is

motorest

CPython is the de-facto reference implementation of Python.

Pypy was developed by reverse engineering CPython and their automated tests feature explicit comparisons with CPyton.

You made the opposite point you thought you were making.

librasteve

in raku, the test suite (ROAST) is the spec

any compiler that can pass ROAST is valid

NeutralForest

That seems uncalled for, the docs are great and the various guides are usually a good starting point to understand and then use the stdlib.

troupo

> Twenty five years ago it was the gold standard of documenting software.

That was PHP. Though Python was a close second

sundarurfriend

Aside: In the process of submitting this, I learnt that Hacker News apparently has an anti-censorship title transform built-in. I submitted it with the title taken from the notebook - "What the f*ck Python!" - and HN automatically removed the ! and changed "f*ck" to "Fuck".

procaryote

I'm happy to complain about python but I got like a third into it and didn't find any actual wtfs.

Java as contrast has interning wtfs because == between java objects does essentioally what python's `is` does. Python actually made a good choice here and made == do what you'd expect.

Is anyone surprised by `(1 > 0) < 1`? There are languages where it will be rejected because of types, but what else would you expect it do than compare a boolean true to 1?

Is there anything of value later on?

bb88

I think there's a few in there. But most people aren't going to write code that way. It's good to know, and keep in your head, but if you have to think too hard in the future if a piece of code is correct, it's probably better to rewrite it anyway. And weird code like that shows up like a sore thumb in reviews.

g42gregory

I may be wrong, but think a lot of it is undefined behavior. Interpreter may choose to recycle objects or it may not. In case of integers, low enough number in different parts of the program, will be represented by the same object. But if the integer is high enough, different objects will be created. That’s my understanding, but I could be wrong.

pyuser583

Exclamation points are in fact part of the ASCII standard.

ssalazar

I didnt make it past the long list of id() misuses, but its a rookie mistake to confuse referential equality with value equality, and when doing so youre in for a bad time.

globalnode

Some ways of programming in Python require a LOT of mental effort. And some don't. For example you can do a lot in one line in Python, but I usually have to write extensive comments and references to external docs to keep track of what that one line is doing. I think sometimes it would be easier if I just had to write 3 or 4 lines of self evident code and use that as docs instead.

bb88

Having written python professionally for more than a decade, I highly recommend not writing complex one-liners -- unless there's some real benefit to doing so.

The more one-liners there are in the code base, the more impenetrable and harder to debug the code is. Unrolling nested functions and switching comprehensions to lists and if statements often make it cleaner and easier to write unit tests for.

If you rely upon code coverage for unit tests, a complex list comprehension won't help you see if you have hit the branch cases.