- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help - just like using the same code outside of a function will still cause problems.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name bindingDeleting something also changes the name binding, e.g.:
y = 1 def x(): return y # local! del y
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help - just like using the same code outside of a function will still cause problems.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help - just like using the same code outside of a function will still cause problems.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deleting something also changes the name binding, e.g.:
y = 1 def x(): return y # local! del y
Contrary to popular belief, Python is not an "interpreted" language in any meaningful sense. (Those are vanishingly rare now.) The reference implementation of Python compiles Python code in much the same way as Java or C#: it is translated into opcodes ("bytecode") for a virtual machine, which is then emulated. Other implementations must also compile the code; otherwise, eval andcode exec could not properly return an object, and- so that SyntaxErrors could notcan be detected without actually running the code, and in order to implement the "compilation services" portion of the standard library.
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help (just- just like using the same code outside of a function will still cause problems). See https://stackoverflow.com/questions/6039605.will still cause problems.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
Contrary to popular belief, Python is not an "interpreted" language in any meaningful sense. (Those are vanishingly rare now.) The reference implementation of Python compiles Python code in much the same way as Java or C#: it is translated into opcodes ("bytecode") for a virtual machine, which is then emulated. Other implementations must also compile the code; otherwise, eval and exec could not properly return an object, and SyntaxErrors could not be detected without actually running the code.
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help (just like using the same code outside of a function will still cause problems). See https://stackoverflow.com/questions/6039605.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
Contrary to popular belief, Python is not an "interpreted" language in any meaningful sense. (Those are vanishingly rare now.) The reference implementation of Python compiles Python code in much the same way as Java or C#: it is translated into opcodes ("bytecode") for a virtual machine, which is then emulated. Other implementations must also compile the code - so that SyntaxErrors can be detected without actually running the code, and in order to implement the "compilation services" portion of the standard library.
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help - just like using the same code outside of a function will still cause problems.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help (just like using the same code outside of a function will still cause problems). See https://stackoverflow.com/questions/6039605.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help (just like using the same code outside of a function will still cause problems). See https://stackoverflow.com/questions/6039605.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y
- It does not matter if the global variable is a builtin function etc., rather than an explicitly created global:
(Of course, it is a bad idea to shadow builtin names like this anyway, anddef x(): int = int('1') # `int` is local!globalcannot help (just like using the same code outside of a function will still cause problems). See https://stackoverflow.com/questions/6039605.) - It does not matter if the code could never be reached:
y = 1 def x(): return y # local! if False: y = 0 - It does not matter if the assignment would be optimized into an in-place modification (e.g. extending a list) - conceptually, the value is still assigned, and this is reflected in the bytecode in the reference implementation as a useless reassignment of the name to the same object:
y = [] def x(): y += [1] # local, even though it would modify `y` in-place with `global` - However, it does matter if we do an indexed/slice assignment instead. (This is transformed into a different opcode at compile time, which will in turn call
__setitem__.)y = [0] def x(): print(y) # global now! No error occurs. y[0] = 1 - There are other forms of assignment, e.g.
forloops andimports:import sys y = 1 def x(): return y # local! for y in []: pass def z(): print(sys.path) # `sys` is local! import sys - Another common way to cause problems with
importis trying to reuse the module name as a local variable, like so:
Again,import random def x(): random = random.choice(['heads', 'tails'])importis assignment, so there is a global variablerandom. But this global variable is not special; it can just as easily be shadowed by the localrandom. - Deletion is also changing the name binding, e.g.:
y = 1 def x(): return y # local! del y