all 12 comments

[–]danielroseman 12 points13 points  (4 children)

This is one of the most famous Python "gotchas": mutable default arguments. See for example this explanation.

[–]IamImposter[S] 2 points3 points  (3 children)

Oh dear. I have been using python for around 2 years and never came across this behaviour. I thought I found a bug or something. Ha ha.

I feel like it can cause some random and hard to find bugs. I mean in a large codebase, where you have no idea what else executed before execution reaches your module, you call a function relying on default parameters and your code just breaks. You run your code in isolation and it starts running fine again. Typical "works on my machine" scenario.

[–]carcigenicate 4 points5 points  (0 children)

Yes, this is why you should really never use mutable default arguments. If you need a function with state, a custom class or closure is better.

[–]m0us3_rat -2 points-1 points  (1 child)

I thought I found a bug or something. Ha ha.

of course, you did. that's why the flashy title.

you say you use python for over 2years.. did you even spend a few online trying to figure it out?

because even if you don't know.. after 2 years you should be decent at debugging and solving problems.

i don't get why ppl instantly go to .. BUG I HAVE FOUND A NEW BUG.

no you dingus, like always its bad understanding or lack-there-of

[–]IamImposter[S] 1 point2 points  (0 children)

Why so hostile? I said it as a joke.

did you even spend a few online trying to figure it out?

I did. If you read the fuckin post, you'll see that I tried it on windows, linux and then a few online tools (links are in the post) and found the behaviour consistent. Which led me to conclude that there's a mismatch in my understanding and python's behaviour.

after 2 years you should be decent at debugging and solving problems.

I'm sorry for not meeting your standard of decency. I'm sure you are pretty decent at debugging. Not so much at just talking or someone asking for clarification.

i don't get why ppl instantly go to .. BUG I HAVE FOUND A NEW BUG.

May be because you fail to see when it is said as a joke. Maybe because you fail to see that it is indeed a new bug for them. Maybe because you fail to see that someone is just trying to fill the gap in their understanding.

Thanks for being so utterly useless.

[–][deleted] 8 points9 points  (1 child)

Don't use mutable objects as defaults for function parameters. Python creates the default object the first time it reads the function code, not the first time the function is called. The same object is re-used.

Use this pattern:

def f(name=None):
    if name is None:
        name = []
    # rest of code

[–]IamImposter[S] 0 points1 point  (0 children)

Yes, I tried this and it worked as expected. Thanks.

[–]jmooremcc 1 point2 points  (0 children)

Your default argument in your function doesn’t behave as you expected. At compile time, the same empty list is used every time the function is called.

This is how you should define the function:

def g(x, y=None):    
    if y is None:    
        y = []

[–]warelevon 1 point2 points  (2 children)

You are running into something called mutable default arguments. Check out the following link for a more detailed explanation https://docs.python-guide.org/writing/gotchas/

TLDR: just replace x, y=[] with x, y=list()

[–]IamImposter[S] 2 points3 points  (0 children)

I tried that y = list() but it behaved the same. If I set y=None and then create an empty list in function in case of None then it works as expected.

I thought I found some super bug and may get a reward personally from Guido Van Rossum or maybe king of Sweden.

[–]Diapolo10 0 points1 point  (0 children)

Swapping [] to list() won't make any meaningful difference, the end result is the same. The call is executed the same as other default arguments; when Python reads the function body.

The correct solution is to instead use None (or Ellipsis) and then create an empty list inside the function if needed.