3 ms·
I'm surprised to see mutable default values not mentioned. It's bitten me more than once to discover that: def f(xs = []): xs.append(5) ret
by adenozine 5y ago
I'm surprised to see mutable default values not mentioned. It's bitten me more than once to discover that:
def f(xs = []):
xs.append(5)
return xs
print(f())
print(f())
will print:
[5]
[5,5]
and I love python despite this horrendous decision, but it should be mentioned more often in beginner resources.
edit: thanks for the downvote? I've answered on the order of dozens of questions about this very mechanic on SO, via IRC, and more... it's a well-known confusing factor
- kubb 5y agoDon't let it get to you. If you're critical of something, someone will always downvote. On the other hand this behavior means that the default value will only get computed once, so I guess Guido thought it's useful if that value comes e.g. from an expensive function. On the other other hand you could achieve that latter behavior with a lazy function even if the arguments were reevaluated every time you call the function. What do others like Common Lisp and Ruby do here?
- jinwoo68 5y agoIn Common Lisp, default values of optional parameters are evaluated each time (only when the argument is not given of course). They can even reference other arguments that come earlier.
- orf 5y agoDefault values for keywords are saved as part of the function signature itself, at function definition time. Without this it’s not clear how you’d introspect the default kwarg values of a function? Would they be computed every time the function is inspected? If they are lazy then what if the default value is expensive to compute or has side effects? So I would not say it’s a horrendous decision, it’s a clear trade off that IMO fits quite well in the Python ethos - everything is an object, and everything can be introspected.
- maple3142 5y agoIt might be confusing as it is different from some other languages, such as C++ and JavaScript. They both evaluate default parameter when the function are called.
- orf 5y agoThe difference is neither of these can introspect a functions arguments at runtime. C++ probably doesn’t need to, as it can do it at compile time with templates, but therein lies the difference. Not to say that it can’t is not confusing (at least to begin with), but it’s not an oversight. It’s a conscious choice and I think the only safe one you can make.
- dinkleberg 5y agoWoah TIL. That does seem like a very strange decision.
- Too 5y agoUse a linter. Almost all of them warn about this footgun.