Consider this code:
def main():
l = []
def func():
l += [1]
func()
print(l)
if __name__ == '__main__':
main()
It will produce:
Traceback (most recent call last):
File "/Users/tahsmith/Library/Preferences/PyCharm2017.1/scratches/scratch_21.py", line 14, in <module>
main()
File "/Users/tahsmith/Library/Preferences/PyCharm2017.1/scratches/scratch_21.py", line 11, in main
func()
File "/Users/tahsmith/Library/Preferences/PyCharm2017.1/scratches/scratch_21.py", line 9, in func
l += [1]
UnboundLocalError: local variable 'l' referenced before assignment
This itself can be fixed by either using nonlocal l at the start of func or using __iadd__ directly instead of +=.
Question: Why is nonlocal needed here?
This is very surprising to me.
+=is the augmented assignment operator; it roughly translates to:If you were to replace
l += [1]with a call toobject.__iadd__(), you can't ignore the return value of that call if you were to use it properly:Both of those translations also need a
nonlocalstatement, because both accessland assign back tol.You can get away with ignoring the return value of
object.__iadd__because list objects are mutable; the list is mutated in-place. But then you may as well use thelist.extend()call in that case:list.__iadd__(), under the covers, callslist.extend()before returningself.