mirror of
https://github.com/satwikkansal/wtfpython.git
synced 2024-09-11 20:17:08 +03: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
|
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.
|
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
|
# Contributing
|
||||||
|
|
||||||
All patches are Welcome! Filing an issue first before submitting a patch will be appreciated :)
|
All patches are Welcome! Filing an issue first before submitting a patch will be appreciated :)
|
||||||
|
Loading…
Reference in New Issue
Block a user