1
0
mirror of https://github.com/satwikkansal/wtfpython synced 2024-11-22 11:04:25 +01:00

Update content.md

This commit is contained in:
Satwik Kansal 2019-06-07 23:48:51 +05:30 committed by Satwik
parent 810dbe1582
commit f8a7d38b70

View File

@ -1,9 +1,10 @@
<p align="center"><img src="/images/logo.png" alt=""></p> <p align="center"><img src="/images/logo.png" alt=""></p>
<h1 align="center"> What the f*ck Python! 🐍 </h1> <h1 align="center">What the f*ck Python! 🐍</h1>
<p align="center"> An interesting collection of surprising snippets and lesser-known Python features.</p> <p align="center">An interesting collection of surprising snippets and lesser-known Python features.</p>
[![WTFPL 2.0][license-image]][license-url] [![WTFPL 2.0][license-image]][license-url]
Translations: [Chinese 中文](https://github.com/leisurelicht/wtfpython-cn)
Python, being a beautifully designed high-level and interpreter-based programming language, provides us with many features for the programmer's comfort. But sometimes, the outcomes of a Python snippet may not seem obvious to a regular user at first sight. Python, being a beautifully designed high-level and interpreter-based programming language, provides us with many features for the programmer's comfort. But sometimes, the outcomes of a Python snippet may not seem obvious to a regular user at first sight.
@ -13,7 +14,7 @@ While some of the examples you see below may not be WTFs in the truest sense, bu
If you're an experienced Python programmer, you can take it as a challenge to get most of them right in first attempt. You may be already familiar with some of these examples, and I might be able to revive sweet old memories of yours being bitten by these gotchas :sweat_smile: If you're an experienced Python programmer, you can take it as a challenge to get most of them right in first attempt. You may be already familiar with some of these examples, and I might be able to revive sweet old memories of yours being bitten by these gotchas :sweat_smile:
If you're a returning reader, you can learn about the new modifications [here](https://github.com/satwikkansal/wtfpython/releases/). PS: If you're a returning reader, you can learn about the new modifications [here](https://github.com/satwikkansal/wtfpython/releases/).
So, here we go... So, here we go...
@ -77,7 +78,7 @@ So, here we go...
- [▶ Yes, it exists!](#-yes-it-exists) - [▶ Yes, it exists!](#-yes-it-exists)
- [▶ Inpinity *](#-inpinity-) - [▶ Inpinity *](#-inpinity-)
- [▶ Mangling time! *](#-mangling-time-) - [▶ Mangling time! *](#-mangling-time-)
- [Section: Miscallaneous](#section-miscallaneous) - [Section: Miscellaneous](#section-miscellaneous)
- [▶ `+=` is faster](#--is-faster) - [▶ `+=` is faster](#--is-faster)
- [▶ Let's make a giant string!](#-lets-make-a-giant-string) - [▶ Let's make a giant string!](#-lets-make-a-giant-string)
- [▶ Explicit typecast of strings](#-explicit-typecast-of-strings) - [▶ Explicit typecast of strings](#-explicit-typecast-of-strings)
@ -200,10 +201,10 @@ Makes sense, right?
+ In the snippets above, strings are implicitly interned. The decision of when to implicitly intern a string is implementation dependent. There are some facts that can be used to guess if a string will be interned or not: + In the snippets above, strings are implicitly interned. The decision of when to implicitly intern a string is implementation dependent. There are some facts that can be used to guess if a string will be interned or not:
* All length 0 and length 1 strings are interned. * All length 0 and length 1 strings are interned.
* Strings are interned at compile time (`'wtf'` will be interned but `''.join(['w', 't', 'f']` will not be interned) * Strings are interned at compile time (`'wtf'` will be interned but `''.join(['w', 't', 'f']` will not be interned)
* Strings that are not composed of ASCII letters, digits or underscores, are not interned. This explains why `'wtf!'` was not interned due to `!`. * 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)
<img src="/images/string-intern/string_intern.png" alt=""> <img src="/images/string-intern/string_intern.png" alt="">
+ 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!"` is not implicitly interned as per the facts mentioned above). It's a compiler optimization and specifically applies to the interactive environment. + 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!"` is not implicitly interned as per the facts mentioned above). It's a compiler optimization and specifically applies to the interactive environment.
+ Constant folding is a technique for [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) in Python. This means the expression `'a'*20` is replaced by `'aaaaaaaaaaaaaaaaaaaa'` during compilation to reduce few clock cycles during runtime. But since the python bytecode generated after compilation is stored in `.pyc` files, the strings greater than length of 20 are discarded for peephole optimization (Why? Imagine the size of `.pyc` file generated as a result of the expression `'a'*10**10`) + Constant folding is a technique for [peephole optimization](https://en.wikipedia.org/wiki/Peephole_optimization) in Python. This means the expression `'a'*20` is replaced by `'aaaaaaaaaaaaaaaaaaaa'` during compilation to reduce 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.
--- ---
@ -241,7 +242,7 @@ some_dict[5] = "Python"
True True
``` ```
**Note:** Objects with different values may also have same hash (known as hash collision). **Note:** Objects with different values may also have same hash (known as hash collision).
* When the statement `some_dict[5] = "Python"` is executed, the existing value "JavaScript" is overwritten with "Python" because Python recongnizes `5` and `5.0` as the same keys of the dictionary `some_dict`. * When the statement `some_dict[5] = "Python"` is executed, the existing value "JavaScript" is overwritten with "Python" because Python recognizes `5` and `5.0` as the same keys of the dictionary `some_dict`.
* This StackOverflow [answer](https://stackoverflow.com/a/32211042/4354153) explains beautifully the rationale behind it. * This StackOverflow [answer](https://stackoverflow.com/a/32211042/4354153) explains beautifully the rationale behind it.
--- ---
@ -296,16 +297,24 @@ True
* But why did the `is` operator evaluated to `False`? Let's see with this snippet. * But why did the `is` operator evaluated to `False`? Let's see with this snippet.
```py ```py
class WTF(object): class WTF(object):
def __init__(self): print("I ") def __init__(self): print("I")
def __del__(self): print("D ") def __del__(self): print("D")
``` ```
**Output:** **Output:**
```py ```py
>>> WTF() is WTF() >>> WTF() is WTF()
I I D D I
I
D
D
False
>>> id(WTF()) == id(WTF()) >>> id(WTF()) == id(WTF())
I D I D I
D
I
D
True
``` ```
As you may observe, the order in which the objects are destroyed is what made all the difference here. As you may observe, the order in which the objects are destroyed is what made all the difference here.
@ -530,7 +539,7 @@ And when the `board` is initialized by multiplying the `row`, this is what happe
We can avoid this scenario here by not using `row` variable to generate `board`. (Asked in [this](https://github.com/satwikkansal/wtfpython/issues/68) issue). We can avoid this scenario here by not using `row` variable to generate `board`. (Asked in [this](https://github.com/satwikkansal/wtfpython/issues/68) issue).
```py ```py
>>> board = [(['']*3)*3] # board = = [['']*3 for _ in range(3)] >>> board = [['']*3 for _ in range(3)]
>>> board[0][0] = "X" >>> board[0][0] = "X"
>>> board >>> board
[['X', '', ''], ['', '', ''], ['', '', '']] [['X', '', ''], ['', '', ''], ['', '', '']]
@ -547,7 +556,7 @@ for x in range(7):
def some_func(): def some_func():
return x return x
funcs.append(some_func) funcs.append(some_func)
results.append(some_func()) results.append(some_func()) # note the function call here
funcs_results = [func() for func in funcs] funcs_results = [func() for func in funcs]
``` ```
@ -766,10 +775,10 @@ for item in mixed_list:
**Output:** **Output:**
```py ```py
>>> booleans_found_so_far
0
>>> integers_found_so_far >>> integers_found_so_far
4 4
>>> booleans_found_so_far
0
``` ```
2\. 2\.
@ -830,7 +839,7 @@ class C(A):
pass pass
``` ```
**Ouptut:** **Output:**
```py ```py
>>> A.x, B.x, C.x >>> A.x, B.x, C.x
(1, 1, 1) (1, 1, 1)
@ -1148,7 +1157,7 @@ str
>>> s = SomeClass('s') >>> s = SomeClass('s')
>>> some_dict[s] = 40 >>> some_dict[s] = 40
>>> some_dict >>> some_dict
{'s': 40} {'s': 40, 's': 42}
>>> keys = list(some_dict.keys()) >>> keys = list(some_dict.keys())
>>> type(keys[0]), type(keys[1]) >>> type(keys[0]), type(keys[1])
(__main__.SomeClass, str) (__main__.SomeClass, str)
@ -1697,7 +1706,7 @@ a += [5, 6, 7, 8]
* The expression `a = a + [5,6,7,8]` generates a new list and sets `a`'s reference to that new list, leaving `b` unchanged. * The expression `a = a + [5,6,7,8]` generates a new list and sets `a`'s reference to that new list, leaving `b` unchanged.
* The expression `a + =[5,6,7,8]` is actually mapped to an "extend" function that operates on the list such that `a` and `b` still point to the same list that has been modified in-place. * The expression `a += [5,6,7,8]` is actually mapped to an "extend" function that operates on the list such that `a` and `b` still point to the same list that has been modified in-place.
--- ---
@ -1895,7 +1904,7 @@ Sshh.. It's a super secret.
#### 💡 Explanation: #### 💡 Explanation:
+ `antigravity` module is one of the few easter eggs released by Python developers. + `antigravity` module is one of the few easter eggs released by Python developers.
+ `import antigravity` opens up a web browser pointing to the [classic XKCD comic](http://xkcd.com/353/) about Python. + `import antigravity` opens up a web browser pointing to the [classic XKCD comic](http://xkcd.com/353/) about Python.
+ Well, there's more to it. There's **another easter egg inside the easter egg**. If look at the [code](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), there's a function defined that purports to implement the [XKCD's geohashing algorithm](https://xkcd.com/426/). + Well, there's more to it. There's **another easter egg inside the easter egg**. If you look at the [code](https://github.com/python/cpython/blob/master/Lib/antigravity.py#L7-L17), there's a function defined that purports to implement the [XKCD's geohashing algorithm](https://xkcd.com/426/).
--- ---
@ -2115,7 +2124,7 @@ AttributeError: 'Yo' object has no attribute '__honey'
True True
``` ```
Why did `Yo()._Yo__honey` worked? Only Indian readers would understand. Why did `Yo()._Yo__honey` work? Only Indian readers would understand.
#### 💡 Explanation: #### 💡 Explanation:
@ -2127,7 +2136,7 @@ Why did `Yo()._Yo__honey` worked? Only Indian readers would understand.
--- ---
## Section: Miscallaneous ## Section: Miscellaneous
### ▶ `+=` is faster ### ▶ `+=` is faster
@ -2350,7 +2359,7 @@ The idea and design for this collection were initially inspired by Denys Dovhan'
* https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines * https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines
* https://stackoverflow.com/questions/1011431/common-pitfalls-in-python * https://stackoverflow.com/questions/1011431/common-pitfalls-in-python
* https://www.python.org/doc/humor/ * https://www.python.org/doc/humor/
* https://www.satwikkansal.xyz/archives/posts/python/My-Python-archives/ * https://www.codementor.io/satwikkansal/python-practices-for-efficient-code-performance-memory-and-usability-aze6oiq65
# 🎓 License # 🎓 License
@ -2365,12 +2374,12 @@ The idea and design for this collection were initially inspired by Denys Dovhan'
If you have any wtfs, ideas or suggestions, please share. If you have any wtfs, ideas or suggestions, please share.
## Want to share wtfpython with friends? ## Surprise your geeky pythonist friends?
You can use these quick links for Twitter and Linkedin. You can use these quick links to recommend wtfpython to your friends,
[Twitter](https://twitter.com/intent/tweet?url=https://github.com/satwikkansal/wtfpython&hastags=python,wtfpython) | [Twitter](https://twitter.com/intent/tweet?url=https://github.com/satwikkansal/wtfpython&hastags=python,wtfpython)
[Linkedin](https://www.linkedin.com/shareArticle?url=https://github.com/satwikkansal&title=What%20the%20f*ck%20Python!&summary=An%20interesting%20collection%20of%20subtle%20and%20tricky%20Python%20snippets.) | [Linkedin](https://www.linkedin.com/shareArticle?url=https://github.com/satwikkansal&title=What%20the%20f*ck%20Python!&summary=An%20interesting%20collection%20of%20subtle%20and%20tricky%20Python%20snippets.)
## Need a pdf version? ## Need a pdf version?