mirror of
https://github.com/satwikkansal/wtfpython
synced 2024-11-21 18:54:20 +01:00
Add examples:
* The disappearing variable to outer scope * Return in both `try` and `finally` clauses
This commit is contained in:
parent
f45b8abeeb
commit
4c922b3280
159
wtfpy.md
159
wtfpy.md
@ -409,10 +409,167 @@ def another_func():
|
||||
UnboundLocalError: local variable 'a' referenced before assignment
|
||||
```
|
||||
|
||||
**Explanation:**
|
||||
### Explanation
|
||||
When you make an assignment to a variable in a scope, it becomes local to that scope. So `a` becomes local to the scope of `another_func` but it has not been initialized previously in the same scope which throws an error. Read [this](http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html) short but awesome guide to learn more about how namespaces and scope resolution works in Python.
|
||||
|
||||
|
||||
## The disappearing variable from outer scope
|
||||
|
||||
```py
|
||||
e = 7
|
||||
try:
|
||||
raise Exception()
|
||||
except Exception as e:
|
||||
pass
|
||||
```
|
||||
|
||||
**Output (Python 2.x):**
|
||||
```py
|
||||
>>> print(e)
|
||||
# prints nothing
|
||||
```
|
||||
|
||||
**Output (Python 3.x):**
|
||||
```py
|
||||
>>> print(e)
|
||||
NameError: name 'e' is not defined
|
||||
```
|
||||
|
||||
### Explanation
|
||||
|
||||
* Source: https://docs.python.org/3/reference/compound_stmts.html#except
|
||||
|
||||
When an exception has been assigned using as target, it is cleared at the end of the except clause. This is as if
|
||||
|
||||
```py
|
||||
except E as N:
|
||||
foo
|
||||
```
|
||||
|
||||
was translated to
|
||||
|
||||
```py
|
||||
except E as N:
|
||||
try:
|
||||
foo
|
||||
finally:
|
||||
del N
|
||||
```
|
||||
|
||||
This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
|
||||
|
||||
* The clauses are not scoped in Python. Everything in the example is present in same scope and the variable `e` got removed due to the execution of the `except` clause. The same is not the case with functions which have their separate inner-scopes. The example below illustrates this:
|
||||
|
||||
```py
|
||||
def f(x):
|
||||
del(x)
|
||||
print(x)
|
||||
|
||||
x = 5
|
||||
y = [5, 4, 3]
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```py
|
||||
>>>f(x)
|
||||
UnboundLocalError: local variable 'x' referenced before assignment
|
||||
>>>f(y)
|
||||
UnboundLocalError: local variable 'x' referenced before assignment
|
||||
>>> x
|
||||
5
|
||||
>>> y
|
||||
[5, 4, 3]
|
||||
```
|
||||
|
||||
* In Python 2.x the variable name `e` gets assigned to `Exception()` instance, so when you try to print, it prints nothing.
|
||||
|
||||
**Output (Python 2.x):**
|
||||
```py
|
||||
>>> e
|
||||
Exception()
|
||||
>>> print e
|
||||
# Nothing is printed!
|
||||
```
|
||||
|
||||
|
||||
## Return in both `try` and `finally` clauses
|
||||
|
||||
```py
|
||||
def some_func():
|
||||
try:
|
||||
return 'from_try'
|
||||
finally:
|
||||
return 'from_finally'
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```py
|
||||
>>> some_func()
|
||||
'from_finally'
|
||||
```
|
||||
|
||||
### Explanation
|
||||
|
||||
When a `return`, `break` or `continue` statement is executed in the `try` suite of a "try…finally" statement, the `finally` clause is also executed ‘on the way out. The return value of a function is determined by the last `return` statement executed. Since the `finally` clause always executes, a `return` statement executed in the `finally` clause will always be the last one executed.
|
||||
|
||||
## When True is actually False
|
||||
|
||||
## The GIL messes it up (Multithreading vs Mutliprogramming example)
|
||||
|
||||
## Take care of the operator precedence buddy! (located inside GIL thread)
|
||||
|
||||
```py
|
||||
>>> True is False == False
|
||||
False
|
||||
>>> False is False is False
|
||||
True
|
||||
```
|
||||
|
||||
## Implicit conversion can hurt sometimes
|
||||
|
||||
```py
|
||||
>>> True + 1
|
||||
2
|
||||
```
|
||||
|
||||
## a += b doesn't behave the same way as a = a+b
|
||||
|
||||
```
|
||||
>>> a=[1,2,3,4]
|
||||
>>> b=a
|
||||
>>> a=a+[5,6,7,8]
|
||||
>>> a
|
||||
[1, 2, 3, 4, 5, 6, 7, 8]
|
||||
>>> b
|
||||
[1, 2, 3, 4]
|
||||
|
||||
|
||||
>>> a=[1,2,3,4]
|
||||
>>> b=a
|
||||
>>> a+=[5,6,7,8]
|
||||
>>> a
|
||||
[1, 2, 3, 4, 5, 6, 7, 8]
|
||||
>>> b
|
||||
[1, 2, 3, 4, 5, 6, 7, 8]
|
||||
```
|
||||
|
||||
## That "is" on the same non-static method of the class instance returns False. It was the first and the last time I tried prettify my code with "is".
|
||||
|
||||
## Some title
|
||||
```
|
||||
x = {0: None}
|
||||
|
||||
for i in x:
|
||||
del x[i]
|
||||
x[i+1] = None
|
||||
print i
|
||||
```
|
||||
|
||||
## Minor ones
|
||||
|
||||
- join() is a string operation instead of list operation. (sort of counterintuitive)
|
||||
- No multicore support yet
|
||||
|
||||
# Contributing
|
||||
|
||||
All patches are Welcome! Filing an issue first before submitting a patch will be appreciated :)
|
||||
|
Loading…
Reference in New Issue
Block a user