Obfuscating references to the same (mutable) object with references to individual objects is really "gotcha" (it suffers from all non-functional languages ββthat have mutable objects and, of course, links). A common mistake in Python code for beginners incorrectly uses the default value, which can be changed, for example:
def addone(item, alist=[]): alist.append(item) return alist
This code may be correct if the goal is to addone to maintain its own state (and return one growing list to consecutive subscribers), since static data will work in C; this is not true if the encoder mistakenly believes that a new empty list will be created with each call.
The original newbies used for functional languages ββcan also be confused by the separation of the command line in Python's design solutions: mutating methods that have nothing in particular to return (i.e. the vast majority of mutation methods) return nothing (in particular, they come back None ) - they do all their work on the spot. Errors arising from misunderstanding are easy to detect, for example.
alist = alist.append(item)
pretty much guaranteed to be an error - it adds an item to the list denoted by the name alist , but then restores the name alist to None (the return value of the append call).
While the first issue I mentioned is about early binding, which can be confusing for people who think that binding is not late, there are problems that go differently when some people expect early binding , instead, the binding is belated. For example (with a hypothetical GUI ...):
for i in range(10): Button(text="Button #%s" % i, click=lambda: say("I'm #%s!" % i))
ten buttons with the inscription "Button # 0", "Button # 1", etc. will be shown here, but each time they are pressed, each of them will say it #9 - because i inside lambda delayed (with a lexical closure). The fix is ββto take advantage of the fact that the default values ββfor the early binding argument (as I pointed out the first problem! -) and change the last line to
click=lambda i=i: say("I'm #%s!" % i))
Now lambda i is an argument with a default value, and not a free variable (distorted by lexical closure), and therefore, the code works as intended (of course, there are other ways).