diff --git a/wtfpython-pypi/content.md b/wtfpython-pypi/content.md index 486a98e..9827fc4 100644 --- a/wtfpython-pypi/content.md +++ b/wtfpython-pypi/content.md @@ -1,9 +1,10 @@

-

What the f*ck Python! 🐍

-

An interesting collection of surprising snippets and lesser-known Python features.

+

What the f*ck Python! 🐍

+

An interesting collection of surprising snippets and lesser-known Python features.

[![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. @@ -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 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... @@ -77,7 +78,7 @@ So, here we go... - [▶ Yes, it exists!](#-yes-it-exists) - [▶ Inpinity *](#-inpinity-) - [▶ Mangling time! *](#-mangling-time-) - - [Section: Miscallaneous](#section-miscallaneous) + - [Section: Miscellaneous](#section-miscellaneous) - [▶ `+=` is faster](#--is-faster) - [▶ Let's make a giant string!](#-lets-make-a-giant-string) - [▶ Explicit typecast of strings](#-explicit-typecast-of-strings) @@ -97,22 +98,22 @@ All the examples are structured like below: > ### ▶ Some fancy Title * > The asterisk at the end of the title indicates the example was not present in the first release and has been recently added. -> +> > ```py > # Setting up the code. > # Preparation for the magic... > ``` -> +> > **Output (Python version):** > ```py > >>> triggering_statement > Probably unexpected output > ``` > (Optional): One line describing the unexpected output. -> -> +> +> > #### 💡 Explanation: -> +> > * Brief explanation of what's happening and why is it happening. > ```py > Setting up examples for clarification (if necessary) @@ -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: * 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 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) + 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 ``` **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. --- @@ -296,16 +297,24 @@ True * But why did the `is` operator evaluated to `False`? Let's see with this snippet. ```py class WTF(object): - def __init__(self): print("I ") - def __del__(self): print("D ") + def __init__(self): print("I") + def __del__(self): print("D") ``` **Output:** ```py >>> WTF() is WTF() - I I D D + I + I + D + D + False >>> 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. @@ -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). ```py ->>> board = [(['']*3)*3] # board = = [['']*3 for _ in range(3)] +>>> board = [['']*3 for _ in range(3)] >>> board[0][0] = "X" >>> board [['X', '', ''], ['', '', ''], ['', '', '']] @@ -547,7 +556,7 @@ for x in range(7): def some_func(): return x funcs.append(some_func) - results.append(some_func()) + results.append(some_func()) # note the function call here funcs_results = [func() for func in funcs] ``` @@ -766,10 +775,10 @@ for item in mixed_list: **Output:** ```py ->>> booleans_found_so_far -0 >>> integers_found_so_far 4 +>>> booleans_found_so_far +0 ``` 2\. @@ -830,7 +839,7 @@ class C(A): pass ``` -**Ouptut:** +**Output:** ```py >>> A.x, B.x, C.x (1, 1, 1) @@ -1135,7 +1144,7 @@ str and type(other) is SomeClass and super().__eq__(other) ) - + # When we define a custom __eq__, Python stops automatically inheriting the # __hash__ method, so we need to define it as well __hash__ = str.__hash__ @@ -1148,7 +1157,7 @@ str >>> s = SomeClass('s') >>> some_dict[s] = 40 >>> some_dict - {'s': 40} + {'s': 40, 's': 42} >>> keys = list(some_dict.keys()) >>> type(keys[0]), type(keys[1]) (__main__.SomeClass, str) @@ -1313,7 +1322,7 @@ Shouldn't that be 100? > 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 <...> * So the "tab" at the last line of `square` function is replaced with eight spaces, and it gets into the loop. * Python 3 is kind enough to throw an error for such cases automatically. - + **Output (Python 3.x):** ```py TabError: inconsistent use of tabs and spaces in indentation @@ -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 + =[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. --- @@ -1731,7 +1740,7 @@ UnboundLocalError: local variable 'a' referenced before assignment a += 1 return a ``` - + **Output:** ```py >>> another_func() @@ -1895,7 +1904,7 @@ Sshh.. It's a super secret. #### 💡 Explanation: + `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. -+ 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 ``` -Why did `Yo()._Yo__honey` worked? Only Indian readers would understand. +Why did `Yo()._Yo__honey` work? Only Indian readers would understand. #### 💡 Explanation: @@ -2127,7 +2136,7 @@ Why did `Yo()._Yo__honey` worked? Only Indian readers would understand. --- -## Section: Miscallaneous +## Section: Miscellaneous ### ▶ `+=` is faster @@ -2272,7 +2281,7 @@ nan ### ▶ Minor Ones * `join()` is a string operation instead of list operation. (sort of counter-intuitive at first usage) - + **💡 Explanation:** 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. @@ -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/1011431/common-pitfalls-in-python * 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 @@ -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. -## 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) | -[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.) +[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.) ## Need a pdf version?