What’s the output of the following code:
ans = []
def bt():
for i in range(3):
ans += [i]
bt()
print(ans)
It will raise an exception, which may beyond your expectation.
UnboundLocalError: local variable 'ans' referenced before assignment
And how about this code.
ans = []
def bt():
for i in range(3):
ans.append(i)
bt()
print(ans)
Yes, it works well and prints [1, 2, 3]
. And let’s see the bytecode of the above code.
6 0 SETUP_LOOP 26 (to 28)
2 LOAD_GLOBAL 0 (range)
4 LOAD_CONST 1 (3)
6 CALL_FUNCTION 1
8 GET_ITER
>> 10 FOR_ITER 14 (to 26)
12 STORE_FAST 0 (i)
7 14 LOAD_GLOBAL 1 (ans)
16 LOAD_ATTR 2 (append)
18 LOAD_FAST 0 (i)
20 CALL_FUNCTION 1
22 POP_TOP
24 JUMP_ABSOLUTE 10
>> 26 POP_BLOCK
>> 28 LOAD_CONST 0 (None)
30 RETURN_VALUE
LOAD_GLOBAL
command before ans
means it tries to load the global variable ans
.
But the bytecode of the exceptional code says it loads a local variable ans
.
6 0 SETUP_LOOP 26 (to 28)
2 LOAD_GLOBAL 0 (range)
4 LOAD_CONST 1 (3)
6 CALL_FUNCTION 1
8 GET_ITER
>> 10 FOR_ITER 14 (to 26)
12 STORE_FAST 0 (i)
7 14 LOAD_FAST 1 (ans)
16 LOAD_FAST 0 (i)
18 BUILD_LIST 1
20 INPLACE_ADD
22 STORE_FAST 1 (ans)
24 JUMP_ABSOLUTE 10
>> 26 POP_BLOCK
>> 28 LOAD_CONST 0 (None)
30 RETURN_VALUE
This is not a bug, but a design choice:
Python does not require you to declare variables, but assumes that a variable assigned in the body of a function is local.
If you want to treat ans
as a global variable in spite of the assignment within the function, use global
declaration:
ans = []
def bt():
for i in range(3):
global ans
ans += [i]
bt()
print(ans)
Reference