5 ms·
I'll be that person I asked ChatGPT: > Gary Berhnhardt gave a famous talk called "Wat" about Javascript. Can you create similar "Wat" style examples for Pytho
by softwaredoug 4y ago
I'll be that person
I asked ChatGPT:
> Gary Berhnhardt gave a famous talk called "Wat" about Javascript. Can you create similar "Wat" style examples for Python?
The examples it gave me were... not that 'wat'-y
Sure, here are some "Wat"-style examples for Python:
1. Unpacking tuples:
>>> a, b = (1, 2)
>>> a
1
>>> b
2
>>> a, b = 1, 2
>>> a
1
>>> b
2
2. Division by zero:
>>> 1 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
Though this one is interesting:
4. Using the is operator:
>>> x = 256
>>> y = 256
>>> x is y
True
>>> x = 257
>>> y = 257
>>> x is y
False
- capableweb 4y agoI gave it a try as well, and GPT-4 taught me something new about Python (I don't normally write Python, so it's not surprising): def add_to_list(value, target_list=[]): target_list.append(value) return target_list list1 = add_to_list(1) list2 = add_to_list(2) print(list1) # [1, 2] print(list2) # [1, 2] In this example, one might expect list1 to contain only 1 and list2 to contain only 2. However, because the default value for the target_list parameter is mutable, it gets shared between function calls, leading to unexpected behavior. The other examples it gave me were not that unexpected. Prompt was: > Show me examples of where Python type inference works in unexpected ways.
- roywiggins 4y ago> because the default value for the target_list parameter is mutable, it gets shared between function calls bit of a weird way to phrase it, I think they're always shared between function calls, you just don't notice when they're not mutable.
- masklinn 4y agoThat is correct, default values are initialised at compilation time and stored in the function object.
- afraca 4y agoSome people might not know this yet, the common idiom is to have the default value be None, and then start your function with checking if it's None and initializing to empty list.
- reportgunner 4y agoThe whole function just makes no sense, it's just `target_list.append(value)` with extra steps.
- capableweb 4y agoYou're missing the point if you're looking at how "useful" this example function is
- reportgunner 4y agoNo, the example is just not good.
- capableweb 4y agoAh, yeah, compared to the examples in the video that makes so much sense in a normal day to day application. I commonly do the following operations without much thought: [] + [] {} + {} [] + {} {} + [] Great examples :) The point is not what the data or naming of the functions/variables is, but what's happening when you run it...
- reportgunner 4y ago[] + [] is more likely to happen than taking list.append(value) and defining a function that does list.append(value) and then returns whatever list.append(value) returns. Hint: list.append(value) returns None
- xdennis 4y ago`[] + []` is unlikely to happen except by accident if you don't know that's how array concatenation is done in JavaScript. But wanting to provide default values of [] is quite common in Python. Seeing this workaround is quite common in Python: def func(arg=None): if arg is None: arg = [] ...
- js2 4y ago(4) is because Python interns small integers and the "is" operator tests identity, not equivalence. Any Python linter will catch that mistake. Python does not coerce types, so it doesn't have very many wats like the ones in this talk.
- squeaky-clean 4y agoPython itself warns you nowadays too, it will print out <dis>:1: SyntaxWarning: "is" with a literal. Did you mean "=="? Some more weird/fun stuff about that: If you throw that code into one file instead of a repl, `x is 257` will be True. If you instead instantiate `x = 257` in a different file, and import it, `x is 257` be False again. In a repl if you run them on the same line it ends up as True! >>> x = 257 >>> print(x is 257) False >>> y = 257; print(y is 257) True If they're in the same file (or same line in a repl), the integer literals are loaded into the `co_consts` object during the initial parse to bytecode, and so they refer to the same object. This only works for integer literals and simple statements that can be optimized to literals by python (e.g. it also works for `x = 257+1; print(x is 258)` >>> dis.dis('y = 257+1; print(y is 258)') 1 0 LOAD_CONST 0 (258) 2 STORE_NAME 0 (y) 4 LOAD_NAME 1 (print) 6 LOAD_NAME 0 (y) 8 LOAD_CONST 0 (258) 10 IS_OP 0 12 CALL_FUNCTION 1 14 POP_TOP 16 LOAD_CONST 1 (None) 18 RETURN_VALUE
- deleted 4y ago[deleted]
- aaronharnly 4y agoIn Python 2 you can redefine the True and False “constants”, which is pretty WAT-y though admittedly tampering. > True = False > if not True: print “can’t happen” can’t happen
- eyelidlessness 4y agoAnd here I was thinking it’s hilarious that JS `undefined` is assignable! I’m sure there’s good historical reason for this, but being able to change booleans to mean their opposite is something extra special to me
- klodolph 4y agoI think the only reason is because it is not specifically prohibited.
- eyelidlessness 4y agoHeh I think that’s the reason for JS undefined too
- runarberg 4y agoThere are quite a few assignable keywords in modern JavaScript. This is actually cromulent JavaScript: of = "wat"; for (of of of) of
- asicsp 4y agoYou'll have better results with https://github.com/satwikkansal/wtfpython https://github.com/satwikkansal/wtfpython
- pansa2 4y agoSee https://github.com/satwikkansal/wtfpython https://github.com/satwikkansal/wtfpython "Mutating the immutable" is my personal favourite - the second line of code fails with an exception despite having already succeeded: >>> t = ([1, 2], 5, 6) >>> t[0] += [3, 4] TypeError: 'tuple' object does not support item assignment >>> print(t) ([1, 2, 3, 4], 5, 6) I've never been a fan of the decision to have `a += b` sometimes do `a = a + b` and sometimes update `a` in place. My objection was initially just due to theoretical inelegance - but this code shows that decision directly causing a concrete problem.
- masklinn 4y agoSadly the core team decided to not learn from that mistake, and did the exact same thing with the dict merge operator.
- omaranto 4y agoBryce Adelstein Lelbach, the ISO C++ Library evolution chair, says that he would rather be consistently wrong than inconsistently right. Maybe that's what the Python core team thought, "we'd better make this consistent with +=, whose quirks people already know".
- masklinn 4y agoThat strikes me as a turbocharged version of the sunk cost fallacy.
- omoikane 4y agoMy favorite python quirk is this expression: -1/3 == -(1/3) Where I would ask people what it evaluates to, and give them the choices: "True", "False", or "Python 2 or Python 3?"
- reportgunner 4y agoWhen would this evaluate to False ?
- planede 4y agoApparently it's False in python2. Python2 does integer division that rounds towards negative infinity. It makes the order of operations important in -1/3. (-1)/3 (and hence -1/3) evaluates to -1, and -(1/3) evaluates to 0.
- kaba0 4y agoThe first example here is one common gotcha I know of: https://docs.python-guide.org/writing/gotchas/ https://docs.python-guide.org/writing/gotchas/ (Didn’t read the rest, but based on the title it may also be relevant)
- zach_garwood 4y agoI remember encountering number 4 in the wild, so I think it deserves to be a genuine "wat". That said, I'm not sure why I (or anyone else) thought I would need to use the identity operator on numbers, but it's certainly a head-scratcher until you dig into the underlying reason.
- owl57 4y agoMaybe such code is written by people scarred by JavaScript and trying to avoid ==. But not sure: I saw this in the wild as well — actually, the victim brought the broken function to chat scratching his head — and he was a quite experienced backend guy (and the experience wasn't in nodejs, AFAIK). A pretty funny kind of bug, actually: it was some relatively simple function, passing the unit tests but doing some nonsense on real data. Thing is, it was comparing some sequential ids and working perfectly as long as there were no more than 256 objects.