for e in collections: pass
In the for loop, the last object e always exists in the context. Even outside the loop, the subsequent reference to e is still valid.
There is a problem here that is easily overlooked. If an object with the same name already exists before the loop, this object will be overwritten.
If you are in a code-aware IDE, the IDE will prompt that the variable is "redeclared", but there will be no error when running.
The for loop is not a closure, you can use the dis module to decompose the following code as you can see:
x = 5 for x in range(10): pass print x
Save the code to the test.py file and run python -m dis test.py
C:UsersPatrickDesktop> python -m dis test.py 1 3 3 6 SETUP_LOOP 20 (to 29)
9 LOAD_NAME 1 (range)
12 LOAD_CONST 1 10 : 28 POP_BLOCK
6 >> 29 LOAD_NAME 0 (x)
32 PRINT_ITEM
33 PRINT_NEWLINE
34 LOAD_CONST 2 (None)
37 RETURN_VALUE
In other languages, the initialization variables of the for loop are also visible to the context, such as Java, because Java is a strongly typed language, if you re-declare an existing variable, the IDE will prompt an error, which of course is different from compilation.
Usually in python programming (probably most dynamic languages), sometimes even if a variable with the same name is declared, there is no obvious error in the program, but once an error occurs, it is difficult to find the error. So avoid having the same name as the variable in the for loop.
This is especially true when coding in the python template language. The code editor has no prompts and will not find out where the error is. This is an extremely weird example that I encountered. Why do you say weird, because there is no logical problem.
{{ page.name if page else ''}}
The problem is here, an error occurred during operation, the prompt is in {{ page.name if page else ''}}
The error page referenced before assignment.
During the template calling process, the template language is also translated into python bytecode and parsed and output line by line, so there is no logic at all. I don’t know if it is a bug in the tornado template language.
So pay attention to the variable names. In short, I think tornado’s exception trace is very unfriendly. The scope search order of variables in Python: local scope (Local) → local scope where the current scope is embedded (Enclosing locals) → global/module scope (Global) → built-in scope (Built-in)