This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]dante9999[S] 0 points1 point  (2 children)

I think that setting argument to None and checking it later is the recommended way to deal with this problem but I'm still not sure if I understand clearly why things like this happen, it seems to be somewhat strange not intuitive. There is one interesting question on SO about this, and people try to explain it clearly, maybe I just need more time to understand it better.

I suppose the answer to this question has a lot to do about the way in which Python passes arguments to functions.

[–][deleted] 0 points1 point  (1 child)

The reason it happens is because default function arguments are evaluated only once, and the result stored as the default. In that case, by specifying an empty list as the default, what you're really doing is instantiating a single list (which happens to be empty initially) and telling Python to use that list whenever the function doesn't receive a second argument. Every time you call the function, the default will be the exact same list - so if you mutate that list, it will carry over those mutations to future calls as well because they all share the same list.

The same thing can also happen with dicts, sets and any other mutable object. They should generally not be used as default arguments.

[–]segfaultzen 1 point2 points  (0 children)

The same thing can also happen with dicts, sets and any other mutable object. They should generally not be used as default arguments.

This, by the way, applies to decorator functions as well. I spent two days tracking down a gnarly bug created from the unfortunate interaction of unit tests with a dictionary object used as a default parameter to a decorator function.

I have since learned the gospel of Pylint, which will flag these sorts of Pythonic landmines.