-1

Why the default value assignmnet defined for a variable in a function is not executed every time we call the function? For example check out this example:

def foo(var=[]):  
   var.append(1)
   return var

foo()
[1]

foo()
[1,1]

when running the function the 2nd time, the default value of the var variable is already set to be one while we clearly asked the function to set it to an empty list if the function is called with no values! What's the logic behind this behavior?

Amin Shn
  • 357
  • 1
  • 7
  • https://stackoverflow.com/q/1132941/4983469 This has a detailed answer to your question – leoOrion May 27 '22 at 08:25
  • Long story short. Python function definitions are interpreted only once. So if you use a mutable parameter, its initial value is set only once at start. After that it keeps track of all the mutations that happen to it. To avoid this, set `var=None` and do a `if var is None: var = []` at start of the function. – leoOrion May 27 '22 at 08:29
  • @leoOrion thanks for the info. I know the solution but I think it does more harm than good to just evaluate the default assignment during the function definition and then ignore that assignment when calling the function and stick to the value of the parameter which could have been changed in numerous ways creating a mess. – Amin Shn May 27 '22 at 08:44
  • 1
    Thats a long standing debate. Ive learned to live with it,... – leoOrion May 27 '22 at 08:45
  • 1
    Well, the most convincing explanation is this: https://stackoverflow.com/a/1133013/476. Whether you like it or not is up to you. – deceze May 27 '22 at 08:50
  • @deceze His argument sounds weird. Who sets the default value to an object defined outside of the function?! The problem he raised could be simply solved by doing 'def eat(food= ("apples", "bananas", "loganberries"))' instead of 'def eat(food= fruits))' which is what everyone does when defining a function. – Amin Shn May 27 '22 at 09:01
  • `import some_module` `def foo(bar=some_module.SOME_CONSTANT): ...` — Seems pretty common. – deceze May 27 '22 at 09:03
  • @deceze And that's a dangerous thing to do and we are told to avoid it. Experts recommend what leoOrion suggested above: setting var=None and do a if var is None: var = something. In fact "Mutable default arguments are dangerous!" is a thing thought in Python programming courses. – Amin Shn May 27 '22 at 09:21
  • Why is that dangerous? I simply want to use a `CONSTANT` as a default argument. But Python "constants" aren't constants, they can be changed. It would arguably be a bug to change your nominal "constant", but here we are. By evaluating the "constant" at declaration time and binding only its value as default value, at least that isn't a source of failure. *It makes sense within Python's design.* It might not make sense when compared to other languages, and yes, it does have its pitfalls. But then so does every other language. – deceze May 27 '22 at 09:25
  • @deceze Python constants are truly constant if they are immutable like integers. But lists or other objects like in your example are mutable and are recommended not to be used as default because then you have to keep track of the status of the function in order to predict its outcome which would be an unnecessary struggle and doesn't make sense neither within Python nor within any other programming language. – Amin Shn May 27 '22 at 10:03
  • No, Python doesn't have *constants.* By that I mean something like `const foo = 'bar'`. Python doesn't have it. Python has *immutable values*, but not *immutable names*. In my examples above I give no hint what kind of value `SOME_CONSTANT` is. But `SOME_CONSTANT` can be reassigned at any time. So if you evaluate the value of `SOME_CONSTANT` at function call time, that's a different and less predictable behaviour than evaluating it at function declaration time. – deceze May 27 '22 at 10:09
  • @deceze You give no reason as to why evaluation of the SOME_CONSTANT at function call is less predictable than ONLY at function declaration time? I would argue the opposite and I gave my reason: You have to keep track of the status of the function to predict its outcome while evaluation at declaration as well as at the call gives you more control. – Amin Shn May 27 '22 at 10:23
  • The answer I linked to previously lays it out perfectly. Again: you are free to disagree with it. But it is how it is. If you want to program in Python, you have little choice but to accept it as is. – deceze May 27 '22 at 10:26

0 Answers0