You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+24-7Lines changed: 24 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -298,12 +298,30 @@ True
298
298
>>> a is b
299
299
False
300
300
301
+
```
302
+
303
+
3\.
304
+
305
+
```py
301
306
>>> a, b="wtf!", "wtf!"
302
-
>>> a is b
307
+
>>> a is b# All versions except 3.7.x
303
308
True
309
+
310
+
>>>a="wtf!"; b="wtf!"
311
+
>>> a is b
312
+
False
304
313
```
305
314
306
-
3\.
315
+
```py
316
+
# This time in file some_file.py
317
+
a="wtf!"
318
+
b="wtf!"
319
+
print(a is b)
320
+
321
+
# prints True when the module is invoked!
322
+
```
323
+
324
+
4\.
307
325
308
326
**Output (< Python3.7 )**
309
327
@@ -324,8 +342,9 @@ Makes sense, right?
324
342
* Strings are interned at compile time (`'wtf'` will be interned but `''.join(['w', 't', 'f']` will not be interned)
325
343
* Strings that are not composed of ASCII letters, digits or underscores, are not interned. This explains why `'wtf!'` was not interned due to `!`. Cpython implementation of this rule can be found [here](https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19)
+ When `a`and`b` are set to `"wtf!"`in the same line, the Python interpreter creates a new object, then references the second variable at the same time. If you do it on separate lines, it doesn't "know" that there's already `wtf!`as an object (because `"wtf!"`isnot implicitly interned as per the facts mentioned above). It's a compiler optimization and specifically applies to the interactive environment. This optimization doesn't apply to 3.7.x versions of CPython (check this [issue](https://github.com/satwikkansal/wtfpython/issues/100) for more discussion).
328
-
+ The abrupt change in output of the third snippet is due to a [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) technique known as Constant folding. This means the expression `'a'*20`is replaced by `'aaaaaaaaaaaaaaaaaaaa'` during compilation to save a few clock cycles during runtime. Constant folding only occurs for strings having length less than 20. (Why? Imagine the size of `.pyc`file generated as a result of the expression `'a'*10**10`). [Here's](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288) the implementation source for the same.
345
+
+ When `a`and`b` are set to `"wtf!"`in the same line, the Python interpreter creates a new object, then references the second variable at the same time. If you do it on separate lines, it doesn't "know" that there's already `wtf!`as an object (because `"wtf!"`isnot implicitly interned as per the facts mentioned above). It's an compile time optimization. This optimization doesn't apply to 3.7.x versions of CPython (check this [issue](https://github.com/satwikkansal/wtfpython/issues/100) for more discussion).
346
+
+ The compile unit in interactive environment consists of single statement, whereas it consists of the entire module in case of modules. `a, b = "wtf!", "wtf!"`is single statement, whereas `a = "wtf!"; b = "wtf!"` are 2 statements in single line. This explains why the identities are different in`a = "wtf!"; b = "wtf!"`, and also explain why they are same when invoked in`some_file.py`
347
+
+ The abrupt change in output of the fourth snippet is due to a [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) technique known as Constant folding. This means the expression `'a'*20`is replaced by `'aaaaaaaaaaaaaaaaaaaa'` during compilation to save a few clock cycles during runtime. Constant folding only occurs for strings having length less than 20. (Why? Imagine the size of `.pyc`file generated as a result of the expression `'a'*10**10`). [Here's](https://github.com/python/cpython/blob/3.6/Python/peephole.c#L288) the implementation source for the same.
329
348
+ Note: In Python 3.7, Constant folding was moved out from peephole optimizer to the new AST optimizer with some change in logic as well, so the third snippet doesn't work for Python 3.7. You can read more about the change [here](https://bugs.python.org/issue11549).
330
349
331
350
---
@@ -861,16 +880,14 @@ Similar optimization applies to other **immutable** objects like empty tuples as
861
880
862
881
* When a and b are set to `257`in the same line, the Python interpreter creates a new object, then references the second variable at the same time. If you do it on separate lines, it doesn't "know" that there's already `257`as an object.
863
882
864
-
* It's a compiler optimization and specifically applies to the interactive environment. When you enter two lines in a live interpreter, they're compiled separately, therefore optimized separately. If you were to try this example in a `.py`file, you would not see the same behavior, because the fileis compiled all at once. This optimization isnot limited to integers, it works for other immutable data types like strings and floats as well.
883
+
* It's a compiler optimization and specifically applies to the interactive environment. When you enter two lines in a live interpreter, they're compiled separately, therefore optimized separately. If you were to try this example in a `.py`file, you would not see the same behavior, because the fileis compiled all at once. This optimization isnot limited to integers, it works for other immutable data types like strings (check the "Strings are tricky example") and floats as well,
865
884
866
885
```py
867
886
>>> a, b = 257.0, 257.0
868
887
>>> a is b
869
888
True
870
889
```
871
890
872
-
873
-
874
891
* Why didn't this work for Python 3.7? The abstract reason is because such compiler optimizations are implementation specific (i.e. may change with version, OS, etc). I'm still figuring out what exact implementation change cause the issue, you can check out this [issue](https://github.com/satwikkansal/wtfpython/issues/100) for updates.
0 commit comments