[HN Gopher] What the Fuck Python
       ___________________________________________________________________
        
       What the Fuck Python
        
       Author : sundarurfriend
       Score  : 74 points
       Date   : 2025-07-19 19:01 UTC (3 hours ago)
        
 (HTM) web link (colab.research.google.com)
 (TXT) w3m dump (colab.research.google.com)
        
       | alabhyajindal wrote:
       | 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.
        
         | heavenlyblue wrote:
         | 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 wrote:
           | 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 wrote:
           | `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
        
         | bnchrch wrote:
         | 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 wrote:
           | 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 wrote:
             | Unless you're doing AI, in which case you're royally
             | screwed.
        
         | moffkalast wrote:
         | 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.
        
           | bnchrch wrote:
           | Don't forget its transitive dependencies creating non-
           | deterministic builds
        
           | 3eb7988a1663 wrote:
           | 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!")
        
             | moffkalast wrote:
             | 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.
        
             | crazygringo wrote:
             | > _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.
        
               | 3eb7988a1663 wrote:
               | prefer bool() threw an exception on receiving a string,
               | rather than act the way it does now.
               | 
               | That breaks the truthiness cornerstone of the language.
               | You can write                 a = 1 # or [], (), "yo",
               | "false", 3.2, MyFooClass(), (1,), False       if a:
               | fire_ze_missles()       else:         declare_peace()
               | 
               | Upon encountering `a`, Python is evaluating bool(a). If
               | that no longer works for strings, you now need a separate
               | code path for determining a non-empty string.
               | 
               | It can short-circuit the brain upon reading a word that
               | you know means false, but the Python rules are
               | consistent. "Empty" is False, everything else is True.
        
               | moffkalast wrote:
               | You can write that yes, but I'm calling the police.
        
           | librasteve wrote:
           | yeah
           | 
           | in raku, i checked                 say False.so; #False
        
             | Jtsummers wrote:
             | If I understand raku correctly, the Python example would be
             | more like this:                 say "False".Bool
             | 
             | Which displays True. 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:         ...
        
         | motorest wrote:
         | > 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?
        
         | fragmede wrote:
         | wat
         | 
         | https://www.destroyallsoftware.com/talks/wat
        
         | throwaway314155 wrote:
         | 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.
        
       | ltbarcly3 wrote:
       | Haha these aren't even wtfs! the id changes or not? oh noooo,
       | people use the id() function so much, I've literally seen it 0
       | times ever in production code. This is nothing like the JS wtfs
       | where there is no way to predict what it will do, and it violates
       | it's own patterns.
       | 
       | edit: to be more clear, I have run into a lot of JS wtf's trying
       | to write code for work. you just run into bugs all the time where
       | JS doesn't do anything like what would be the obvious thing to
       | do, or the thing that works 99.99% of the time fails depending on
       | the value of the string being 'magic'. with Python I rarely if
       | ever learn some bizarre arcane thing accidentally because it
       | almost always behaves as expected. If you think there's an
       | equivalence here you are just a JS fanboy, JS was a language that
       | evolved largely because of hacks vendors put in and those insane
       | hacks got standardized because it was too late, despite being
       | insane. Python was specifically and carefully designed to
       | minimize unexpected behavior.
        
         | andy_ppp wrote:
         | I think they are pretty bad tbh apart from the ID one. Everyone
         | knows about the JS quirks so I think it's good to know
         | sometimes equality in Python strings can behave extremely
         | strangely and the other issues mentioned. Why does it have to
         | be defended "my language is better than your language"? However
         | I'd like to say Elixir is near perfect, thanks :-)
        
           | ltbarcly3 wrote:
           | No you misread it, equality for python strings works exactly
           | the way you expect. the id() value (which is basically the
           | memory address) might not change if you concatenate strings,
           | but literally nobody ever uses id for anything ever. You
           | would use hash() which does change appropriately.
           | 
           | edit: 'wtf!' is always equal to itself. Maybe you are
           | thinking of `is`, which just compares the value of id(). `is`
           | can't be used for comparisons, saying it's a WTF is just
           | being unfamiliar with basics. `is` is not used for equality
           | comparisons. This is how more or less every language works,
           | comparing pointers is not the same as comparing strings in
           | C/rust/etc. Comparing object identity is not the same as
           | testing equality in Java.
        
             | andy_ppp wrote:
             | I think honestly it is you who misread my comment... I was
             | saying the id() issue isn't a real problem, the weirdness
             | around "wtf!" not being equal to itself under some
             | circumstances is very confusing. Seems Google Colab isn't
             | loading here.
        
               | ziml77 wrote:
               | But "is" doesn't check equality. It checks reference
               | equality. Maybe the real wtf here is they made that check
               | a temptingly short infix operator rather than a function
               | named reference_equals().
        
               | zahlman wrote:
               | "wtf!" _is_ consistently equal to itself in Python.
               | 
               | The fact that you could have separate string objects both
               | representing that text, is entirely orthogonal to that.
        
               | Jtsummers wrote:
               | `is` is more like doing this in C:                 char*
               | s1 = "wtf!";       char* s2 = "wtf!";       if (s1 == s2)
               | { ... }
               | 
               | They may or may not be stored in the same place depending
               | on your compiler (clang and gcc yes, msvc no, at least
               | with just a quick default build). If you actually want to
               | do an _equality_ check, you need to use `==` (in Python)
               | which would be like using `strcmp` in C.
               | 
               | > "wtf!" not being equal to itself
               | 
               | It _is_ equal to itself, but multiple variables
               | referencing that string may not hold references to the
               | _same_ (literal, in memory) string.
        
         | mvanbaak wrote:
         | I totally agree with you. I have seen a lot of code, but the
         | id() function has never been used in production code
        
         | w4yai wrote:
         | And now you're using pretty much the same rhetoric than JS guys
         | when facing to wtfjs.
        
           | ltbarcly3 wrote:
           | No, I don't think so. The JS wtf's actually make you gasp.
           | These are so obscure and boring.
           | 
           | F'ing JS equality isn't transitive for builtin types.
        
           | BobbyTables2 wrote:
           | Even normal JS is WTF-worthy...
           | 
           | Allowing out of bound array indexing and operations using
           | "undefined" seems pretty crazy to me.
        
             | jacquesm wrote:
             | For the former: technically they are about as undefined as
             | they could be on read. On write, it's a different matter
             | (you could decide to resize the array under the hood). Even
             | so, I think arrays with a particular size always were
             | simply an illustration that there is a point where you have
             | to allocate a physical resource to something entirely
             | imaginary and that's where infinite bounds are no longer
             | acceptable. In the 80's that was '256', in the 90's
             | '65535', nowadays it is more like '4G' but no matter how
             | far we advance there are still hard limits. And on the wire
             | it gets even more constrained.
        
         | craftkiller wrote:
         | I think this one is good:                 False == False in
         | [False]       # Outputs True
         | 
         | It doesn't make sense no matter which way you evaluate it.
         | Equality first:                 False == False # True
         | True in [False] # False
         | 
         | or `in` first:                 False in [False] # True
         | False == True # False
        
           | ltbarcly3 wrote:
           | Ok I'll admit this is a real WTF
        
             | Upvoter33 wrote:
             | chained comparisons are weird and counter-intuitive,
             | sometimes
        
               | quuxplusone wrote:
               | Python is my second language (after C++) and for me the
               | surprising thing here is not "chained comparisons are
               | weird" but rather "`in` is a comparison operator."
               | 
               | So for example `1 in [1,2] in [[1,2],[3,4]]` is True...
               | but off the top of my head I don't see any legitimate
               | use-case for that facility. Intuitively, I'd think a
               | "comparison operator" should be homogeneous -- should
               | take the same type on LHS and RHS. So, like, "is-subset-
               | of" could sanely be a comparison operator, but `in` can't
               | be.
        
               | zahlman wrote:
               | >and for me the surprising thing here is not "chained
               | comparisons are weird" but rather "`in` is a comparison
               | operator."
               | 
               | Python documentation calls it a "comparison operator" (ht
               | tps://docs.python.org/3/reference/expressions.html#compar
               | i...) but a broader, better term is "relational
               | operator". It expresses a possible relationship between
               | two arguments, and evaluates whether those arguments have
               | that relationship. In this case, "containment" (which
               | intuitively encompasses set membership and substrings).
               | 
               | A finer distinction could have been made, arguably, but
               | it's far too late to change now. (And everyone is
               | traumatized by the 2->3 transition.)
        
           | None4U wrote:
           | Yeah, having the expansion rule operate on operators that are
           | clearly not transitive serves no purpose (1 < 2 < 3 is at
           | least a math notation)
        
           | daedrdev wrote:
           | Its apparently trying to allow x < y < z be a legal
           | statement, meaning that we get:
           | 
           | False == False and False in [False] is a expansion of that
           | statement, just like x < y and y < z is the expansion of x <
           | y < z
        
           | jnpnj wrote:
           | Oh yeah, that's a great one, there must be a compounded
           | boolean expression logic escaping us
           | 
           | I'll add:                   >>> False == False in [True]
           | False         >>> True == True in [True]         True
           | 
           | ps: some ast poking                   >>>
           | ast.show(ast.parse("False == False in [False]"))
           | Module(           body=[      Expr(        value=Compare(
           | left=Constant(value=False),          ops=[            Eq(),
           | In()],          comparators=[
           | Constant(value=False),            List(       elts=[
           | Constant(value=False)],       ctx=Load())]))])
           | >>> ast.show(ast.parse("(False == False) in [False]"))
           | Module(           body=[      Expr(        value=Compare(
           | left=Compare(            left=Constant(value=False),
           | ops=[       Eq()],            comparators=[
           | Constant(value=False)]),          ops=[            In()],
           | comparators=[            List(       elts=[
           | Constant(value=False)],       ctx=Load())]))])
           | 
           | note the first tree as one Comparator node with multiple ops,
           | time to read the spec to know how these are evaluated
        
             | Jtsummers wrote:
             | The document explains it. When dealing with these
             | comparators, when chained they get separated and you have
             | the equivalent of this:                 False == False in
             | [True]       =>       (False == False) and (False in
             | [True])
             | 
             | If you put it into a function like this:
             | def foo(): return False == False in [True]
             | 
             | And then disassemble it you'll get this byte code (3.13,
             | may vary by version):                 RESUME
             | 0          LOAD_CONST               1 (False)
             | LOAD_CONST               1 (False)          SWAP
             | 2          COPY                     2          COMPARE_OP
             | 72 (==)          COPY                     1
             | TO_BOOL          POP_JUMP_IF_FALSE        5 (to L1)
             | POP_TOP          LOAD_CONST               2 ((True,))
             | CONTAINS_OP              0          RETURN_VALUE       L1:
             | SWAP                     2          POP_TOP
             | RETURN_VALUE
             | 
             | There is no literal `and` operation occurring here, instead
             | it first does the `False == False`, then jumps if false or
             | continues to the second comparison.
             | 
             | For the literals we've given it, it'll go on to the second
             | comparison which will result in false since `False` is not
             | in `(True,)`.
             | 
             | EDIT: And here's the non-chained version disassembled:
             | def bar(): return (False == False) in [True]
             | RESUME                   0          LOAD_CONST
             | 1 (False)          LOAD_CONST               1 (False)
             | COMPARE_OP              72 (==)          LOAD_CONST
             | 2 ((False,))          CONTAINS_OP              0
             | RETURN_VALUE
        
           | its-summertime wrote:
           | return False == False in [False]
           | 
           | is roughly                   a = False         b = False
           | c = [False]         (a == b) and (b in c)
           | 
           | is less roughly                   a = False         b = False
           | if not (a == b):            # short circuits
           | https://news.ycombinator.com/item?id=44619401
           | return False               c = [False]         if not (b in
           | c):            return False              return True
        
           | zahlman wrote:
           | > It doesn't make sense no matter which way you evaluate it
           | 
           | It makes sense when you evaluate it the way it's intended to
           | be understood (https://stackoverflow.com/questions/6074018).
           | There _are_ other languages that do this, and it was
           | consciously designed to work this way. The idea that you
           | should have to evaluate one of the operators  "first" may
           | make sense to someone trying to implement a parser with
           | techniques from the 70s, but for languages like Python, the
           | design is clearly more about what makes sense for the code
           | author.
           | 
           | Arguably it's surprising that `in` is treated as on par with
           | `==`. But on the other hand, even someone trying to implement
           | a parser with techniques from the 70s would have to admit
           | that both are "relational operators".
        
         | kgm wrote:
         | I have used id() in production code, but the circumstances were
         | extremely specific: It was in some monitoring-related code that
         | was trying to dig down into the guts of the interpreter for the
         | purposes of tracking memory usage on the level of individual
         | pages. It was a whole thing.
         | 
         | Which is to say: Users of Python almost certainly don't want to
         | call id(), unless they are mucking around with something
         | related to the functioning of the interpreter itself. The only
         | other circumstance in which I've used it in anything like real
         | code was in a quick hack where what I really wanted was to put
         | a bunch of dicts in a set, but you can't do that, so I made a
         | set of their IDs instead (but this wasn't in what I would call
         | "production code").
         | 
         | In general, most of the "wtfs" listed here are pretty banal. If
         | you're using `is` on immutable objects, you're basically just
         | asking for trouble. The functioning of string and integer
         | interning and constant folding are implementation curiosities,
         | and if you ever write code in which such differences matter,
         | then you have made an error.
        
         | jtolmar wrote:
         | I don't think either reach the real wtfs of their language.
         | id() does some weird things with string interring, javascript
         | coerces cross-type arithmetic into weird nonsense instead of
         | throwing a type error. Whatever, neither of these come up in
         | the real world.
         | 
         | Builds so messy that you need to resort to venv, every second
         | DOM API being someFunc(thirdMostImportantArgument, {
         | mostImportantArgument: val }), these are the real wtfs.
        
           | zahlman wrote:
           | Yes, but those are definitionally library and ecosystem wtfs,
           | rather than language ones.
        
         | zahlman wrote:
         | Like I've been saying in other recent submissions, since there
         | seems to be a trend for similar discussion: in Python you find
         | WTFs by trying to probe how Python works, pushing deliberately
         | over-flexibly customization hooks to their limits, etc. In JS
         | you find them by merely trying to call builtins with dodgy
         | inputs.
        
         | Shacklz wrote:
         | > I have run into a lot of JS wtf's trying to write code for
         | work
         | 
         | JS certainly does have _plenty_ of wtfs but honestly, when
         | sticking to somewhat modern JS, it 's not so bad anymore these
         | days. Function-scoping-shenanigans can mostly be circumvented
         | by simply sticking to const/let, use a 3rd-party-library like
         | date-fns instead of the dumpsterfire that is native Date and
         | you're almost there - throw typescript into the mix and I have
         | a very hard time imagining running into the meme-worthy JS-
         | warts on a daily basis.
        
       | JohnKemeny wrote:
       | If you use a floating point number as a key in a `dict` the wtf
       | should not be pointing at Python.
       | 
       | These are not wtfs, please.
       | 
       | These examples read like someone who is learning to program and
       | who is confused.                   x is not y         x is (not
       | y)
       | 
       | How can you confuse these two?!
        
         | mvanbaak wrote:
         | AI
        
         | woooooo wrote:
         | Fp32 or fp64 in a strongly typed language would be no problem
         | as hash keys. Yes, they're imprecise for math but the 64 bits
         | of data should work just like a long as a hash key.
        
           | marcosdumay wrote:
           | No, they are not suitable for use as hash keys unless you are
           | treating them as opaque binary data. And if you are there,
           | you are better putting your values in some type that means
           | opaque binary data for the start.
        
             | spacechild1 wrote:
             | They are perfectly suitable as long as you know what you
             | are doing. Here's a real use case: when compiling a
             | scripting language, map float constants to slots in a
             | "constant table" so that all constants with the same value
             | share the same slot.
        
             | woooooo wrote:
             | They ARE fixed-width binary data, and they're effectively
             | opaque unless you have IEEE 754 open on your desk, it's all
             | handled in hardware otherwise.
        
       | LPisGood wrote:
       | Some of these just seem to be using Python out of spec and being
       | surprised that implementation details exist, and misunderstanding
       | boolean expressions.
        
         | otabdeveloper4 wrote:
         | 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.)
        
           | troupo wrote:
           | > Twenty five years ago it was the gold standard of
           | documenting software.
           | 
           | That was PHP. Though Python was a close second
        
           | LPisGood wrote:
           | 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 wrote:
             | 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 wrote:
             | in raku, the test suite (ROAST) is the spec
             | 
             | any compiler that can pass ROAST is valid
        
           | simonw wrote:
           | 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-...
        
           | NeutralForest wrote:
           | 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.
        
           | zahlman wrote:
           | 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 wrote:
             | > 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.
        
               | zahlman wrote:
               | The majority of the comment I was replying to was about
               | documentation, and I was responding to that.
        
             | otabdeveloper4 wrote:
             | 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.
        
       | omoikane wrote:
       | See also: https://github.com/satwikkansal/wtfpython
       | 
       | The "interactive notebook" link goes to the colab page.
       | 
       | There are many earlier threads associated with the markdown
       | version, for example:
       | 
       | https://news.ycombinator.com/item?id=21862073 (2019-12-23, 185
       | comments)
       | 
       | https://news.ycombinator.com/item?id=26097732 (2021-02-11, 163
       | comments)
       | 
       | https://news.ycombinator.com/item?id=31566031 (2022-05-31, 143
       | comments)
       | 
       | https://news.ycombinator.com/item?id=37281692 (2023-08-27, 82
       | comments)
        
       | rr808 wrote:
       | While we're at it. Notebooks aren't a real programming
       | environment.
        
         | incognito124 wrote:
         | I don't think anyone is disputing that
        
         | klysm wrote:
         | Huh we must be hallucinating then?
        
         | rexpop wrote:
         | Yeah, this simply doesn't work for me; ie the expressions did
         | not evaluate, and output was not made visible.
         | 
         | I have _never_ had a successful experience writing or running
         | programs in notebooks like this--although I have not, arguably,
         | tried with high stakes.
         | 
         | As soon as the stakes rise that far, however, I reach for a
         | whole-ass Unix environment with a shell, a filesystem, and a
         | stateful process model.
         | 
         | Is this a crutch? Is it too much overhead? It's arguably absurd
         | that I even ask. (Edit: It's actually _killing me_ how
         | ambiguous I 'm being, right now. There's no winning.)
        
           | zahlman wrote:
           | > As soon as the stakes rise that far, however, I reach for a
           | whole-ass Unix environment with a shell, a filesystem, and a
           | stateful process model.
           | 
           | I don't understand what you mean by "reach for". Don't, for
           | example, Linux desktop users have all these things at hand
           | all the time? For me it would take much more effort to set up
           | a "notebook" than a virtual environment.
        
             | fragmede wrote:
             | For you, sure, but for someone that lives and breathes
             | notebooks, running _jupyter notebook_ and going to
             | localhost:8888 already happened, so it 's opening a
             | terminal that's the extra step.
        
               | zahlman wrote:
               | ... How do you do those things without a terminal?
        
               | hollerith wrote:
               | You would start the Jupyter application, then use a
               | browser to go to localhost:8888 :)
               | 
               | To start the application, you would typically use the
               | start menu on Windows or the Dock on MacOS. Alternatively
               | on MacOS you could point the Finder at the /Applications
               | folder, then start the application from the Finder
               | window.
               | 
               | (This is not meant as an endorsement of notebooks.)
        
               | fragmede wrote:
               | install https://github.com/jupyterlab/jupyterlab-desktop
               | and double click
        
         | jacquesm wrote:
         | Agreed. Even so, you'd be surprised to find that some companies
         | run them in production. I never got the idea behind that, maybe
         | someone that engages in such a practice could enlighten me. I
         | have yet to hear a good rationale.
        
           | mr_toad wrote:
           | Programming encompasses things other than production
           | environments and software engineering. Notebooks are fine
           | programming environments for prototyping, exploration and
           | training.
        
         | extraduder_ire wrote:
         | Real in what way? I'm not too familiar with them, but they seem
         | about on par with the environment for JavaScript that is html
         | files or "web pages".
         | 
         | Making a html document so someone can easily run some
         | JavaScript, seems like the closest parallel to making a jupiter
         | notebook so someone can easily run some python.
        
         | moffkalast wrote:
         | Jupyter is like if someone decided they don't like neither REPL
         | nor running complete scripts and did something that makes a
         | mockery of both.
        
         | pseufaux wrote:
         | Define "real programming environment"
         | 
         | Seems like an odd way to say, "Notebooks don't fit my
         | workflow/usecase."
        
       | Danjoe4 wrote:
       | 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.
        
         | motorest wrote:
         | > 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?
        
           | fragmede wrote:
           | 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 wrote:
             | So we shouldn't learn about them? They're offensive to
             | enumerate? No, they're useful to understand.
        
               | fragmede wrote:
               | So we should put them into the bug tracking system and
               | prioritize them accordingly. They're very useful to
               | understand, but if one costs $100 every time it happens
               | but it only happens once a year, vs a different bug that
               | costs $1 every time it gets hit, but it happens every
               | day, which one should get fixed first?
        
             | motorest wrote:
             | 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?
        
               | fragmede wrote:
               | I think you're reading a lot more emotion than exists
               | into my comment. Despair? lol I'm just pointing out that
               | QA testers (and good ones are worth their weight in gold)
               | find bugs by doing things must users wouldn't even
               | consider doing.
               | 
               | https://news.ycombinator.com/item?id=25851770
        
           | FreakLegion wrote:
           | 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.
        
         | duncanfwalker wrote:
         | 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
        
         | evertedsphere wrote:
         | > 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
        
         | crazygringo wrote:
         | > _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.
        
         | happytoexplain wrote:
         | 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.
        
       | hansvm wrote:
       | 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 wrote:
         | Yeah, it would be much clearer if instead of an `a is b`
         | operator, there was a `same_object(a, b)` built-in method.
        
       | procaryote wrote:
       | 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?
        
       | happytoexplain wrote:
       | I'm a little flabbergasted at how many comments here boil down to
       | "These aren't WTFs if you understand the language."
        
         | pseufaux wrote:
         | It's a bit like when non-JS programmers complain about
         | JavaScript. It's mostly nonsense. That's not to say that
         | JavaScript doesn't have flaws and footguns, but the opinion of
         | novices in the language is not who I am interested in learning
         | from. Python is the same. It has flaws and idiosyncrasies,
         | especially in the standard library (cough cough
         | xml.ElementTree), but the core language is fairly consistent
         | and predictable. Expecting casting functions like bool() to
         | parse strings like JavaScript does makes little sense.
        
       ___________________________________________________________________
       (page generated 2025-07-19 23:00 UTC)