The difference between the two is that b += 3
is an assignment -- it is assigning a totally new value (the result of addition of your empty list and 3) to b
. b.append()
, in contrast, mutates the list referenced by b
without reassigning it.
inner()
is accessing a variable in its parent's scope (I think this is not technically a closure since the execution of the parent has not completed). But inner()
can only dereference that name, not assign to it, because b
is not local to inner()
and is not declared as global
or nonlocal
.
So you can dereference b
and mutate the list it refers to, but you cannot assign to it. When you try to assign to it by starting the line with b +=
you are saying "treat b
like a local". On a normal b = 3
assignment this would actually complete successfully, creating a local variable like any other. But in this case, since b
has no already assigned value in the local context, dereferencing b
in order to perform the addition procedure fails.
As it happens, you can't simply add an integer to a list in the first place. +=
is not the same thing as append
even setting aside assignment vs. mutation, so even if you weren't reaching out of scope it would fail with a TypeError
. b += [3]
is closer to what you mean, although it will still fail due to the variable's scope.