4 ms·
This kills it for me too. I rely on pypy, and I just can't see myself sacrificing my productivity by using Six. Also, Python 3 neglected to fix one of the most
by eiopa 11y ago
This kills it for me too. I rely on pypy, and I just can't see myself sacrificing my productivity by using Six.
Also, Python 3 neglected to fix one of the most annoying things about the language - default arg value
def foo(x=[]):
x.append(1)
print x
foo() # 1
foo() # 1 1
Why is this still busted??
- rspeer 11y agoBecause nobody's made a Python Enhancement Proposal for what should happen instead.
- makecheck 11y agoIt may be an easy mistake to make but using None is more consistent and efficient to detect. You can use "if x is None:" for any type; whereas, a function may or may not want to allow empty strings (or even empty lists) and it is easy to use a None check to decide when to apply the desired default.
- nbadg 11y agoAre you referring persistence of mutable default args? Which then potentially leads to bugs when you treat it as a new variable on each function call? This is intentional behavior. It's the result of one-time evaluation of default args, which is important for memoization. It's also really useful in combination with late-binding closures. For example, using a lambda as a generator function: def create_multipliers(): return [lambda x : i * x for i in range(5)] This doesn't work, you'll get all 8's. Instead you need to: def create_multipliers(): return [lambda x, i=i : i * x for i in range(5)] Late-binding closures and memoization strategies are pretty core language features; I wouldn't expect them to change (and many python devs would be pretty pissed if they did). Yes, this can be confusing with mutable default objects, but the alternative is to have disparate behavior depending on the mutability of the defaults, which would be an utter catastrophe. http://docs.python-guide.org/en/latest/writing/gotchas/ http://docs.python-guide.org/en/latest/writing/gotchas/
- alextgordon 11y agoOther languages seem to get it right. Even C++! #include <vector> static int foo(std::vector<int> x = {}) { x.push_back(10); return x.size(); } int main (int argc, char const *argv[]) { printf("%d\n", foo()); // 1 printf("%d\n", foo()); // still 1 return 0; } def foo(x=[]): x.append(10) return len(x) print(foo()) # 1 print(foo()) # 2? wtf?
- eiopa 11y agoES6 got this right too. This design decision makes me die a little every time I have to do: def foo(x=None): if not x: x = [] ...
- dajonker 11y agoThat will get you into trouble as well, please use: if x is None: x = [] ... etc.
- switch007 11y agoOr even "prettier": x = [] if x is None else x
- knite 11y agoI'm partial to: x = x or []
- acveilleux 11y agoOnly works when x is truthy for all legal x values, excluding x=0.
- deleted 11y ago[deleted]
- 11y ago
- throwaway91919 11y agoCan you (or someone) clarify what problem you're talking about? This seems to work as expected for me: def foo(x=[]): sum = 0 for a in x: sum += a return sum print foo([3,5]) # 8 print foo(x=[3]) # 3 print foo([]) # 0 print foo() # 0 Is it the fact that kwargs are required to have defaults? Or what?
- raverbashing 11y agoNah, do it like this def foo(i,x=[]): x.append(i) return x foo(1) foo(2) See what happens
- saltylicorice 11y agoThe problem is that the default argument is mutable. def f(a=[]): a.append('v') print a f(['ok']) # ['ok', 'v'] f() # ['v'] f() # ['v', 'v']
- throwaway91919 11y agoAh, thanks.
- deleted 11y ago[deleted]