Skip to content

Commit 3806284

Browse files
committed
Update content.md
1 parent f03f7dc commit 3806284

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

wtfpython-pypi/content.md

+44-35
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<p align="center"><img src="/images/logo.png" alt=""></p>
2-
<h1 align="center"> What the f*ck Python! 🐍 </h1>
3-
<p align="center"> An interesting collection of surprising snippets and lesser-known Python features.</p>
2+
<h1 align="center">What the f*ck Python! 🐍</h1>
3+
<p align="center">An interesting collection of surprising snippets and lesser-known Python features.</p>
44

55
[![WTFPL 2.0][license-image]][license-url]
66

7+
Translations: [Chinese 中文](https://github.com/leisurelicht/wtfpython-cn)
78

89
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.
910

@@ -13,7 +14,7 @@ While some of the examples you see below may not be WTFs in the truest sense, bu
1314

1415
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:
1516

16-
If you're a returning reader, you can learn about the new modifications [here](https://github.com/satwikkansal/wtfpython/releases/).
17+
PS: If you're a returning reader, you can learn about the new modifications [here](https://github.com/satwikkansal/wtfpython/releases/).
1718

1819
So, here we go...
1920

@@ -77,7 +78,7 @@ So, here we go...
7778
- [▶ Yes, it exists!](#-yes-it-exists)
7879
- [▶ Inpinity *](#-inpinity-)
7980
- [▶ Mangling time! *](#-mangling-time-)
80-
- [Section: Miscallaneous](#section-miscallaneous)
81+
- [Section: Miscellaneous](#section-miscellaneous)
8182
- [`+=` is faster](#--is-faster)
8283
- [▶ Let's make a giant string!](#-lets-make-a-giant-string)
8384
- [▶ Explicit typecast of strings](#-explicit-typecast-of-strings)
@@ -97,22 +98,22 @@ All the examples are structured like below:
9798

9899
> ### ▶ Some fancy Title *
99100
> The asterisk at the end of the title indicates the example was not present in the first release and has been recently added.
100-
>
101+
>
101102
> ```py
102103
> # Setting up the code.
103104
> # Preparation for the magic...
104105
> ```
105-
>
106+
>
106107
> **Output (Python version):**
107108
> ```py
108109
> >>> triggering_statement
109110
> Probably unexpected output
110111
> ```
111112
> (Optional): One line describing the unexpected output.
112-
>
113-
>
113+
>
114+
>
114115
> #### 💡 Explanation:
115-
>
116+
>
116117
> * Brief explanation of what's happening and why is it happening.
117118
> ```py
118119
> Setting up examples for clarification (if necessary)
@@ -200,10 +201,10 @@ Makes sense, right?
200201
+ 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:
201202
* All length 0 and length 1 strings are interned.
202203
* Strings are interned at compile time (`'wtf'` will be interned but `''.join(['w', 't', 'f']` will not be interned)
203-
* Strings that are not composed of ASCII letters, digits or underscores, are not interned. This explains why `'wtf!'` was not interned due to `!`.
204+
* 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)
204205
<img src="/images/string-intern/string_intern.png" alt="">
205206
+ 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.
206-
+ 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`)
207+
+ 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.
207208
208209
209210
---
@@ -241,7 +242,7 @@ some_dict[5] = "Python"
241242
True
242243
```
243244
**Note:** Objects with different values may also have same hash (known as hash collision).
244-
* 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`.
245+
* 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`.
245246
* This StackOverflow [answer](https://stackoverflow.com/a/32211042/4354153) explains beautifully the rationale behind it.
246247
247248
---
@@ -296,16 +297,24 @@ True
296297
* But why did the `is` operator evaluated to `False`? Let's see with this snippet.
297298
```py
298299
class WTF(object):
299-
def __init__(self): print("I ")
300-
def __del__(self): print("D ")
300+
def __init__(self): print("I")
301+
def __del__(self): print("D")
301302
```
302303
303304
**Output:**
304305
```py
305306
>>> WTF() is WTF()
306-
I I D D
307+
I
308+
I
309+
D
310+
D
311+
False
307312
>>> id(WTF()) == id(WTF())
308-
I D I D
313+
I
314+
D
315+
I
316+
D
317+
True
309318
```
310319
As you may observe, the order in which the objects are destroyed is what made all the difference here.
311320
@@ -530,7 +539,7 @@ And when the `board` is initialized by multiplying the `row`, this is what happe
530539
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).
531540
532541
```py
533-
>>> board = [(['']*3)*3] # board = = [['']*3 for _ in range(3)]
542+
>>> board = [['']*3 for _ in range(3)]
534543
>>> board[0][0] = "X"
535544
>>> board
536545
[['X', '', ''], ['', '', ''], ['', '', '']]
@@ -547,7 +556,7 @@ for x in range(7):
547556
def some_func():
548557
return x
549558
funcs.append(some_func)
550-
results.append(some_func())
559+
results.append(some_func()) # note the function call here
551560
552561
funcs_results = [func() for func in funcs]
553562
```
@@ -766,10 +775,10 @@ for item in mixed_list:
766775
767776
**Output:**
768777
```py
769-
>>> booleans_found_so_far
770-
0
771778
>>> integers_found_so_far
772779
4
780+
>>> booleans_found_so_far
781+
0
773782
```
774783
775784
2\.
@@ -830,7 +839,7 @@ class C(A):
830839
pass
831840
```
832841
833-
**Ouptut:**
842+
**Output:**
834843
```py
835844
>>> A.x, B.x, C.x
836845
(1, 1, 1)
@@ -1135,7 +1144,7 @@ str
11351144
and type(other) is SomeClass
11361145
and super().__eq__(other)
11371146
)
1138-
1147+
11391148
# When we define a custom __eq__, Python stops automatically inheriting the
11401149
# __hash__ method, so we need to define it as well
11411150
__hash__ = str.__hash__
@@ -1148,7 +1157,7 @@ str
11481157
>>> s = SomeClass('s')
11491158
>>> some_dict[s] = 40
11501159
>>> some_dict
1151-
{'s': 40}
1160+
{'s': 40, 's': 42}
11521161
>>> keys = list(some_dict.keys())
11531162
>>> type(keys[0]), type(keys[1])
11541163
(__main__.SomeClass, str)
@@ -1313,7 +1322,7 @@ Shouldn't that be 100?
13131322
> First, tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight <...>
13141323
* So the "tab" at the last line of `square` function is replaced with eight spaces, and it gets into the loop.
13151324
* Python 3 is kind enough to throw an error for such cases automatically.
1316-
1325+
13171326
**Output (Python 3.x):**
13181327
```py
13191328
TabError: inconsistent use of tabs and spaces in indentation
@@ -1697,7 +1706,7 @@ a += [5, 6, 7, 8]
16971706
16981707
* The expression `a = a + [5,6,7,8]` generates a new list and sets `a`'s reference to that new list, leaving `b` unchanged.
16991708
1700-
* 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.
1709+
* 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.
17011710
17021711
---
17031712
@@ -1731,7 +1740,7 @@ UnboundLocalError: local variable 'a' referenced before assignment
17311740
a += 1
17321741
return a
17331742
```
1734-
1743+
17351744
**Output:**
17361745
```py
17371746
>>> another_func()
@@ -1895,7 +1904,7 @@ Sshh.. It's a super secret.
18951904
#### 💡 Explanation:
18961905
+ `antigravity` module is one of the few easter eggs released by Python developers.
18971906
+ `import antigravity` opens up a web browser pointing to the [classic XKCD comic](http://xkcd.com/353/) about Python.
1898-
+ 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/).
1907+
+ 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/).
18991908
19001909
---
19011910
@@ -2115,7 +2124,7 @@ AttributeError: 'Yo' object has no attribute '__honey'
21152124
True
21162125
```
21172126
2118-
Why did `Yo()._Yo__honey` worked? Only Indian readers would understand.
2127+
Why did `Yo()._Yo__honey` work? Only Indian readers would understand.
21192128
21202129
#### 💡 Explanation:
21212130
@@ -2127,7 +2136,7 @@ Why did `Yo()._Yo__honey` worked? Only Indian readers would understand.
21272136
21282137
---
21292138
2130-
## Section: Miscallaneous
2139+
## Section: Miscellaneous
21312140
21322141
21332142
### ▶ `+=` is faster
@@ -2272,7 +2281,7 @@ nan
22722281
### ▶ Minor Ones
22732282
22742283
* `join()` is a string operation instead of list operation. (sort of counter-intuitive at first usage)
2275-
2284+
22762285
**💡 Explanation:**
22772286
If `join()` is a method on a string then it can operate on any iterable (list, tuple, iterators). If it were a method on a list, it'd have to be implemented separately by every type. Also, it doesn't make much sense to put a string-specific method on a generic `list` object API.
22782287
@@ -2350,7 +2359,7 @@ The idea and design for this collection were initially inspired by Denys Dovhan'
23502359
* https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines
23512360
* https://stackoverflow.com/questions/1011431/common-pitfalls-in-python
23522361
* https://www.python.org/doc/humor/
2353-
* https://www.satwikkansal.xyz/archives/posts/python/My-Python-archives/
2362+
* https://www.codementor.io/satwikkansal/python-practices-for-efficient-code-performance-memory-and-usability-aze6oiq65
23542363
23552364
# 🎓 License
23562365
@@ -2365,12 +2374,12 @@ The idea and design for this collection were initially inspired by Denys Dovhan'
23652374
23662375
If you have any wtfs, ideas or suggestions, please share.
23672376
2368-
## Want to share wtfpython with friends?
2377+
## Surprise your geeky pythonist friends?
23692378
2370-
You can use these quick links for Twitter and Linkedin.
2379+
You can use these quick links to recommend wtfpython to your friends,
23712380
2372-
[Twitter](https://twitter.com/intent/tweet?url=https://github.com/satwikkansal/wtfpython&hastags=python,wtfpython) |
2373-
[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.)
2381+
[Twitter](https://twitter.com/intent/tweet?url=https://github.com/satwikkansal/wtfpython&hastags=python,wtfpython)
2382+
| [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.)
23742383
23752384
## Need a pdf version?
23762385

0 commit comments

Comments
 (0)