mirror of
https://github.com/satwikkansal/wtfpython.git
synced 2024-09-11 20:17:08 +03:00
Add non reflexive class method and the matmul operator examples
This commit is contained in:
parent
4af4f9debf
commit
312c5d542c
110
README.md
vendored
110
README.md
vendored
@ -1321,6 +1321,48 @@ True
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### ▶ Non-reflexive class methods
|
||||||
|
|
||||||
|
<!-- Example ID: 3649771a-f733-413c-8060-3f9f167b83fd -->
|
||||||
|
|
||||||
|
```py
|
||||||
|
class SomeClass:
|
||||||
|
def instance_method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def class_method(cls):
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> SomeClass.instance_method is SomeClass.instance_method
|
||||||
|
True
|
||||||
|
>>> SomeClass.class_method is SomeClass.class_method
|
||||||
|
False
|
||||||
|
>>> id(SomeClass.class_method) == id(SomeClass.class_method)
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 💡 Explanation:
|
||||||
|
|
||||||
|
- The reason `SomeClass.class_method is SomeClass.class_method` is `False` is due to the `@classmethod` decorator.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> SomeClass.instance_method
|
||||||
|
<function __main__.SomeClass.instance_method(self)>
|
||||||
|
>>> SomeClass.class_method
|
||||||
|
<bound method SomeClass.class_method of <class '__main__.SomeClass'>
|
||||||
|
```
|
||||||
|
|
||||||
|
A new bound method everytime `SomeClass.class_method` is accessed.
|
||||||
|
|
||||||
|
- `id(SomeClass.class_method) == id(SomeClass.class_method)` returned `True` because the second allocation of memory for `class_method` happened at the same location of first deallocation (See Deep Down, we're all the same example for more detailed explanation).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### ▶ yielding None
|
### ▶ yielding None
|
||||||
<!-- Example ID: 5a40c241-2c30-40d0-8ba9-cf7e097b3b53 --->
|
<!-- Example ID: 5a40c241-2c30-40d0-8ba9-cf7e097b3b53 --->
|
||||||
```py
|
```py
|
||||||
@ -2843,7 +2885,7 @@ True
|
|||||||
#### 💡 Explanation:
|
#### 💡 Explanation:
|
||||||
|
|
||||||
* `this` module in Python is an easter egg for The Zen Of Python ([PEP 20](https://www.python.org/dev/peps/pep-0020)).
|
* `this` module in Python is an easter egg for The Zen Of Python ([PEP 20](https://www.python.org/dev/peps/pep-0020)).
|
||||||
* And if you think that's already interesting enough, check out the implementation of [this.py](https://hg.python.org/cpython/file/c3896275c0f6/Lib/this.py). Interestingly, the code for the Zen violates itself (and that's probably the only place where this happens).
|
* And if you think that's already interesting enough, check out the implementation of [this.py](https://hg.python.org/cpython/file/c3896275c0f6/Lib/this.py). Interestingly, **the code for the Zen violates itself** (and that's probably the only place where this happens).
|
||||||
* Regarding the statement `love is not True or False; love is love`, ironic but it's self-explanatory (if not, please see the examples related to `is` and `is not` operators).
|
* Regarding the statement `love is not True or False; love is love`, ironic but it's self-explanatory (if not, please see the examples related to `is` and `is not` operators).
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -2888,7 +2930,7 @@ Try block executed successfully...
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 💡 Explanation:
|
#### 💡 Explanation:
|
||||||
- The `else` clause after a loop is executed only when there's no explicit `break` after all the iterations.
|
- The `else` clause after a loop is executed only when there's no explicit `break` after all the iterations. You can think of it as a "nobreak" clause.
|
||||||
- `else` clause after try block is also called "completion clause" as reaching the `else` clause in a `try` statement means that the try block actually completed successfully.
|
- `else` clause after try block is also called "completion clause" as reaching the `else` clause in a `try` statement means that the try block actually completed successfully.
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -3041,11 +3083,10 @@ AttributeError: 'A' object has no attribute '__variable'
|
|||||||
* So, to access `__honey` attribute in first snippet, we had to append `_Yo` to the front which would prevent conflicts with the same name attribute defined in any other class.
|
* So, to access `__honey` attribute in first snippet, we had to append `_Yo` to the front which would prevent conflicts with the same name attribute defined in any other class.
|
||||||
* But then why didn't it work in the second snippet? Because name mangling excludes the names ending with double underscores.
|
* But then why didn't it work in the second snippet? Because name mangling excludes the names ending with double underscores.
|
||||||
* The third snippet was also a consequence of name mangling. The name `__variable` in the statement `return __variable` was mangled to `_A__variable` which also happens to be the name of the variable we declared in outer scope.
|
* The third snippet was also a consequence of name mangling. The name `__variable` in the statement `return __variable` was mangled to `_A__variable` which also happens to be the name of the variable we declared in outer scope.
|
||||||
|
* Also, if the mangled name is longer than 255 characters truncation will happen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Section: Miscellaneous
|
## Section: Miscellaneous
|
||||||
@ -3205,9 +3246,8 @@ nan
|
|||||||
<!-- Example ID: f885cb82-f1e4-4daa-9ff3-972b14cb1324 --->
|
<!-- Example ID: f885cb82-f1e4-4daa-9ff3-972b14cb1324 --->
|
||||||
* `join()` is a string operation instead of list operation. (sort of counter-intuitive at first usage)
|
* `join()` is a string operation instead of list operation. (sort of counter-intuitive at first usage)
|
||||||
|
|
||||||
**💡 Explanation:**
|
**💡 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.
|
||||||
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.
|
|
||||||
|
|
||||||
* Few weird looking but semantically correct statements:
|
* Few weird looking but semantically correct statements:
|
||||||
+ `[] = ()` is a semantically correct statement (unpacking an empty `tuple` into an empty `list`)
|
+ `[] = ()` is a semantically correct statement (unpacking an empty `tuple` into an empty `list`)
|
||||||
+ `'a'[0][0][0][0][0]` is also a semantically correct statement as strings are [sequences](https://docs.python.org/3/glossary.html#term-sequence)(iterables supporting element access using integer indices) in Python.
|
+ `'a'[0][0][0][0][0]` is also a semantically correct statement as strings are [sequences](https://docs.python.org/3/glossary.html#term-sequence)(iterables supporting element access using integer indices) in Python.
|
||||||
@ -3242,22 +3282,47 @@ nan
|
|||||||
>>> a
|
>>> a
|
||||||
>>> 44
|
>>> 44
|
||||||
```
|
```
|
||||||
**💡 Explanation:**
|
**💡 Explanation:** This prank comes from [Raymond Hettinger's tweet](https://twitter.com/raymondh/status/1131103570856632321?lang=en). The space invader operator is actually just a malformatted `a -= (-1)`. Which is equivalent to `a = a - (- 1)`. Similar for the `a += (+ 1)` case.
|
||||||
This prank comes from [Raymond Hettinger's tweet](https://twitter.com/raymondh/status/1131103570856632321?lang=en). The space invader operator is actually just a malformatted `a -= (-1)`. Which is equivalent to `a = a - (- 1)`. Similar for the `a += (+ 1)` case.
|
|
||||||
|
* Python has an undocumented [converse implication](https://en.wikipedia.org/wiki/Converse_implication) operator.
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> False ** False == True
|
||||||
|
True
|
||||||
|
>>> False ** True == False
|
||||||
|
True
|
||||||
|
>>> True ** False == True
|
||||||
|
True
|
||||||
|
>>> True ** True == True
|
||||||
|
True
|
||||||
|
```
|
||||||
|
|
||||||
|
**💡 Explanation:** If you replace `False` and `True` by 0 and 1 and do the maths, the truth table is equivalent to converse implication operator. ([Source](https://github.com/cosmologicon/pywat/blob/master/explanation.md#the-undocumented-converse-implication-operator))
|
||||||
|
|
||||||
|
* Since we are talking operators, there's also `@` operator for matrix multiplication (don't worry, this time it's for real).
|
||||||
|
|
||||||
|
```py
|
||||||
|
>>> import numpy as np
|
||||||
|
>>> np.array([2, 2, 2]) @ np.array([7, 8, 8])
|
||||||
|
46
|
||||||
|
```
|
||||||
|
|
||||||
|
**💡 Explanation:** The `@` operator was added in Python 3.5 keeping scientific community in mind. Any object can overload `__matmul__` magic method to define behavior for this operator.
|
||||||
|
|
||||||
* Python uses 2 bytes for local variable storage in functions. In theory, this means that only 65536 variables can be defined in a function. However, python has a handy solution built in that can be used to store more than 2^16 variable names. The following code demonstrates what happens in the stack when more than 65536 local variables are defined (Warning: This code prints around 2^18 lines of text, so be prepared!):
|
* Python uses 2 bytes for local variable storage in functions. In theory, this means that only 65536 variables can be defined in a function. However, python has a handy solution built in that can be used to store more than 2^16 variable names. The following code demonstrates what happens in the stack when more than 65536 local variables are defined (Warning: This code prints around 2^18 lines of text, so be prepared!):
|
||||||
|
|
||||||
```py
|
```py
|
||||||
import dis
|
import dis
|
||||||
exec("""
|
exec("""
|
||||||
def f():
|
def f():
|
||||||
""" + """
|
""" + """
|
||||||
""".join(["X" + str(x) + "=" + str(x) for x in range(65539)]))
|
""".join(["X" + str(x) + "=" + str(x) for x in range(65539)]))
|
||||||
|
|
||||||
f()
|
f()
|
||||||
|
|
||||||
print(dis.dis(f))
|
print(dis.dis(f))
|
||||||
```
|
```
|
||||||
|
|
||||||
* Multiple Python threads won't run your *Python code* concurrently (yes you heard it right!). It may seem intuitive to spawn several threads and let them execute your Python code concurrently, but, because of the [Global Interpreter Lock](https://wiki.python.org/moin/GlobalInterpreterLock) in Python, all you're doing is making your threads execute on the same core turn by turn. Python threads are good for IO-bound tasks, but to achieve actual parallelization in Python for CPU-bound tasks, you might want to use the Python [multiprocessing](https://docs.python.org/2/library/multiprocessing.html) module.
|
* Multiple Python threads won't run your *Python code* concurrently (yes you heard it right!). It may seem intuitive to spawn several threads and let them execute your Python code concurrently, but, because of the [Global Interpreter Lock](https://wiki.python.org/moin/GlobalInterpreterLock) in Python, all you're doing is making your threads execute on the same core turn by turn. Python threads are good for IO-bound tasks, but to achieve actual parallelization in Python for CPU-bound tasks, you might want to use the Python [multiprocessing](https://docs.python.org/2/library/multiprocessing.html) module.
|
||||||
|
|
||||||
* Sometimes the `print` method might not print values immediately. For example,
|
* Sometimes the `print` method might not print values immediately. For example,
|
||||||
@ -3281,21 +3346,6 @@ nan
|
|||||||
|
|
||||||
* `int('١٢٣٤٥٦٧٨٩')` returns `123456789` in Python 3. In Python, Decimal characters include digit characters, and all characters that can be used to form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Here's an [interesting story](http://chris.improbable.org/2014/8/25/adventures-in-unicode-digits/) related to this behavior of Python.
|
* `int('١٢٣٤٥٦٧٨٩')` returns `123456789` in Python 3. In Python, Decimal characters include digit characters, and all characters that can be used to form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Here's an [interesting story](http://chris.improbable.org/2014/8/25/adventures-in-unicode-digits/) related to this behavior of Python.
|
||||||
|
|
||||||
* Python has an undocumented [converse implication](https://en.wikipedia.org/wiki/Converse_implication) operator.
|
|
||||||
|
|
||||||
```py
|
|
||||||
>>> False ** False == True
|
|
||||||
True
|
|
||||||
>>> False ** True == False
|
|
||||||
True
|
|
||||||
>>> True ** False == True
|
|
||||||
True
|
|
||||||
>>> True ** True == True
|
|
||||||
True
|
|
||||||
```
|
|
||||||
|
|
||||||
If you replace `False` and `True` by 0 and 1 and do the maths, the truth table is equivalent to converse implication operator. ([Source](https://github.com/cosmologicon/pywat/blob/master/explanation.md#the-undocumented-converse-implication-operator)).
|
|
||||||
|
|
||||||
* `'abc'.count('') == 4`. Here's an approximate implementation of `count` method, which would make the things more clear
|
* `'abc'.count('') == 4`. Here's an approximate implementation of `count` method, which would make the things more clear
|
||||||
```py
|
```py
|
||||||
def count(s, sub):
|
def count(s, sub):
|
||||||
|
Loading…
Reference in New Issue
Block a user