Re: default value for __init__ doesn't work
On Sep 11, 1:14 pm, Benjamin Kaplan benjamin.kap...@case.edu wrote: On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 kelvin@gmail.com wrote: Please look at below code snippet: class test(): def __init__(self, a, dic={}): self.a = a self.dic = dic print('__init__ params:',a, dic) This is a pretty popular mistake to make. Default arguments aren't evaluated when you call the method. They're created when the method is created (meaning when you first run the file and the class itself is defined), and that's it. Because you do self.dic = dic, this means that every instance of the object will receive the same dict object. Change it for one object, and the change will show up in all of them. The solution to this is to use a sentinel value, like None def __init__(self, a, dic=None) : if dic is None : self.dic = {} else : self.dic = dic If None is a valid value for the parameter, make a sentinel object and use that sentinel = object() def __init__(self, a, dic=sentinel) : if dic is sentinel : #you want to use is here, not == ... Got it. Thanks for point out my mistake. You are very nice. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value for __init__ doesn't work
On Sep 11, 1:55 pm, 人言落日是天涯,望极天涯不见家 kelvin@gmail.com wrote: On Sep 11, 1:14 pm, Benjamin Kaplan benjamin.kap...@case.edu wrote: On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 kelvin@gmail.com wrote: Please look at below code snippet: class test(): def __init__(self, a, dic={}): self.a = a self.dic = dic print('__init__ params:',a, dic) This is a pretty popular mistake to make. Default arguments aren't evaluated when you call the method. They're created when the method is created (meaning when you first run the file and the class itself is defined), and that's it. Because you do self.dic = dic, this means that every instance of the object will receive the same dict object. Change it for one object, and the change will show up in all of them. The solution to this is to use a sentinel value, like None def __init__(self, a, dic=None) : if dic is None : self.dic = {} else : self.dic = dic If None is a valid value for the parameter, make a sentinel object and use that sentinel = object() def __init__(self, a, dic=sentinel) : if dic is sentinel : #you want to use is here, not == ... Got it. Thanks for point out my mistake. You are very nice. I remember the same issue was occurred in my C++ program. There I have a function with a parameter referenced a default object . May be C++ also constructs the the default arguments before the function is called. Thank you again to help me so much! -- http://mail.python.org/mailman/listinfo/python-list
Re: default value for __init__ doesn't work
On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 kelvin@gmail.com wrote: Please look at below code snippet: class test(): def __init__(self, a, dic={}): self.a = a self.dic = dic print('__init__ params:',a, dic) This is a pretty popular mistake to make. Default arguments aren't evaluated when you call the method. They're created when the method is created (meaning when you first run the file and the class itself is defined), and that's it. Because you do self.dic = dic, this means that every instance of the object will receive the same dict object. Change it for one object, and the change will show up in all of them. The solution to this is to use a sentinel value, like None def __init__(self, a, dic=None) : if dic is None : self.dic = {} else : self.dic = dic If None is a valid value for the parameter, make a sentinel object and use that sentinel = object() def __init__(self, a, dic=sentinel) : if dic is sentinel : #you want to use is here, not == ... -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In article [EMAIL PROTECTED], Paul McGuire [EMAIL PROTECTED] wrote: On Oct 14, 1:36 pm, David C. Ullrich [EMAIL PROTECTED] wrote: [...] In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... Are you being sarcastic? Why would you think that? Seems like a perfectly reasonable request. Short of import mindreading, I don't know how Python would know which behavior a given user would expect. I guess that's why I'm not a programmer - not able to think this sort of thing through properly. Thanks. This explains a lot of other things I've wondered about for years, like why I need to tell the waitress whether I want tea or coffee, why I sometimes need to switch channels on my TV... that's always been what I like about c.l.py, getting answers to questions I haven't even asked. -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
David C. Ullrich a écrit : In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: (snip) Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Yeps. But I don't think we derive the same conclusions from that point. Erm, I think maybe your irony detector needs a little calibration... Possibly, yes... [...] In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... I was worried someone might not realize I was being sarcastic, which is why I threw in this obvious impossibility If different users expect different - mostly incompatible - things, how would it be possible to have it working the way the user expect ? but I guess it wasn't enough. Obviously not - at least for me. OTHO, I've seen peoples very seriously asking for such obvious impossibilities. Should Python grow some telepathic features to guess the user's expectations and modifies itself to meet these expectations ?-) And the answer is, of course, 42. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Steven D'Aprano wrote: On Sun, 19 Oct 2008 02:52:52 +, Aaron Brady wrote: Steven D'Aprano wrote: On Sat, 18 Oct 2008 09:17:28 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Aaron Castironpi Brady wrote: The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Exactly! Says who? Using arguments for internal-use-only is a perfectly acceptable example of practicality beating purity. That's a stretch. It's a standard Python idiom used by the standard library. It's a compromise solution, where the other compromises are about as good. ...Except for the confused newbies. But why should they pick this feature to ignore the documentation for? It trades off intuitiveness for convenience. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 14, 1:36 pm, David C. Ullrich [EMAIL PROTECTED] wrote: Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Basic Python is so transparent that you can start using it without reading anything, just looking at a few examples. _Because_ of that it's their responsibility to ensure that if you look at a few examples you then have a complete understanding of the language. I agree, Python really does strive to be intuitive and easy-to-learn. So the oddity of the behavior of optional_list_arg=[] is a recurring surprise to those who jump first and read documentation later. Besides the tutorials, reference docs, and FAQs, there are also some web pages with titles like Python Gotchas and Common Mistakes in Python that usually tread this ground too. In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... Are you being sarcastic? Short of import mindreading, I don't know how Python would know which behavior a given user would expect. Maybe instead of a code smell, this particular Python wart is a design smell. What is surprising is that Python cannot discriminate between this: y = 100 def f(a,x=y): print a+x f(1) 101 y=200 f(1) 101 and this: def f(a,x=[]): print a+len(x) x.append(a) f(1) 1 f(1) 2 f(1,[1,2,3]) 4 Is x supposed to be a default arg or a static arg (in the sense of a static var within a function as one finds in C)? -- Paul -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Sun, Oct 19, 2008 at 12:56 AM, Paul McGuire [EMAIL PROTECTED] wrote: On Oct 14, 1:36 pm, David C. Ullrich [EMAIL PROTECTED] wrote: Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Basic Python is so transparent that you can start using it without reading anything, just looking at a few examples. _Because_ of that it's their responsibility to ensure that if you look at a few examples you then have a complete understanding of the language. I agree, Python really does strive to be intuitive and easy-to-learn. So the oddity of the behavior of optional_list_arg=[] is a recurring surprise to those who jump first and read documentation later. Besides the tutorials, reference docs, and FAQs, there are also some web pages with titles like Python Gotchas and Common Mistakes in Python that usually tread this ground too. Specifically: http://www.onlamp.com/pub/a/python/2004/02/05/learn_python.html?page=2 http://www.ferg.org/projects/python_gotchas.html#contents_item_6 http://zephyrfalcon.org/labs/python_pitfalls.html Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... Are you being sarcastic? Short of import mindreading, I don't know how Python would know which behavior a given user would expect. Maybe instead of a code smell, this particular Python wart is a design smell. What is surprising is that Python cannot discriminate between this: y = 100 def f(a,x=y): print a+x f(1) 101 y=200 f(1) 101 and this: def f(a,x=[]): print a+len(x) x.append(a) f(1) 1 f(1) 2 f(1,[1,2,3]) 4 Is x supposed to be a default arg or a static arg (in the sense of a static var within a function as one finds in C)? -- Paul -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Sun, 19 Oct 2008 00:56:17 -0700, Paul McGuire wrote: On Oct 14, 1:36 pm, David C. Ullrich [EMAIL PROTECTED] wrote: ... In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... Are you being sarcastic? Yes, David was being sarcastic. Or possibly ironic. Satirical? One of those humour things. Whatever it was, I think you're the second person who missed it. Short of import mindreading, I don't know how Python would know which behavior a given user would expect. Exactly. Besides, Guido has a time machine, and apparently antigravity is being added to the standard library, so I don't see why we can't have mindreading too. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Sat, 18 Oct 2008 09:17:28 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Aaron Castironpi Brady wrote: The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Exactly! Says who? Using arguments for internal-use-only is a perfectly acceptable example of practicality beating purity. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Steven D'Aprano wrote: On Sat, 18 Oct 2008 09:17:28 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Aaron Castironpi Brady wrote: The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Exactly! Says who? Using arguments for internal-use-only is a perfectly acceptable example of practicality beating purity. That's a stretch. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Sun, 19 Oct 2008 02:52:52 +, Aaron Brady wrote: Steven D'Aprano wrote: On Sat, 18 Oct 2008 09:17:28 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Aaron Castironpi Brady wrote: The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Exactly! Says who? Using arguments for internal-use-only is a perfectly acceptable example of practicality beating purity. That's a stretch. It's a standard Python idiom used by the standard library. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In message [EMAIL PROTECTED], Duncan Booth wrote: We already get people asking why code like this doesn't return 3: fns = [ lambda: x for x in range(10) ] fns[3]() 9 ... making this change to default arguments would mean the solution usually proposed to the function scoping question above would no longer work: fns = [ lambda y=x: y for x in range(10) ] fns[3]() 3 The right solution, of course, is fns = [(lambda x : lambda : x)(x) for x in range(10)] -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Fri, 17 Oct 2008 23:04:52 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Duncan Booth wrote: We already get people asking why code like this doesn't return 3: fns = [ lambda: x for x in range(10) ] fns[3]() 9 ... making this change to default arguments would mean the solution usually proposed to the function scoping question above would no longer work: fns = [ lambda y=x: y for x in range(10) ] fns[3]() 3 The right solution, of course, is fns = [(lambda x : lambda : x)(x) for x in range(10)] Only if by right solution you mean excessively verbose, confusing, and the sort of thing that makes even supporters of lambda cringe. Yes yes, it's just a factory function written with lambdas. It's still ugly and exactly the sort of thing that gives ammunition to lambda- haters. Unlike the solution given by Duncan, which is understandable to any newbie who has learned about default values and lambda, your solution requires an understanding of higher-level functions (functions that return functions, for anyone who doesn't recognise the term) that most newbies won't have. And while I don't much care for premature optimization, I will point out that creating a factory function just to call it once then throw it away is very wasteful, and that waste is demonstrated by the running time being more than double that of Duncan's solution: timeit.Timer('[ lambda y=x: y for x in range(10) ]').repeat() [7.6332600116729736, 6.9825620651245117, 7.0891578197479248] timeit.Timer('[(lambda x : lambda : x)(x) for x in range(10)]').repeat() [18.984915971755981, 17.808281898498535, 18.432481050491333] -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 17, 6:56 am, Steven D'Aprano [EMAIL PROTECTED] cybersource.com.au wrote: On Fri, 17 Oct 2008 23:04:52 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Duncan Booth wrote: We already get people asking why code like this doesn't return 3: fns = [ lambda: x for x in range(10) ] fns[3]() 9 ... making this change to default arguments would mean the solution usually proposed to the function scoping question above would no longer work: fns = [ lambda y=x: y for x in range(10) ] fns[3]() 3 The right solution, of course, is fns = [(lambda x : lambda : x)(x) for x in range(10)] Only if by right solution you mean excessively verbose, confusing, and the sort of thing that makes even supporters of lambda cringe. Yes yes, it's just a factory function written with lambdas. It's still ugly and exactly the sort of thing that gives ammunition to lambda- haters. Unlike the solution given by Duncan, which is understandable to any newbie who has learned about default values and lambda, your solution requires an understanding of higher-level functions (functions that return functions, for anyone who doesn't recognise the term) that most newbies won't have. And while I don't much care for premature optimization, I will point out that creating a factory function just to call it once then throw it away is very wasteful, and that waste is demonstrated by the running time being more than double that of Duncan's solution: timeit.Timer('[ lambda y=x: y for x in range(10) ]').repeat() [7.6332600116729736, 6.9825620651245117, 7.0891578197479248] timeit.Timer('[(lambda x : lambda : x)(x) for x in range(10)]').repeat() [18.984915971755981, 17.808281898498535, 18.432481050491333] -- Steven No, there's a difference in meaning. One creates a function that is called with 0 arguments. The other creates a function that can be called with 0 or 1 arguments. The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Nested namespaces and object attributes can be. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In message [EMAIL PROTECTED], Aaron Castironpi Brady wrote: The purpose of a parameter is something that the caller can supply, but doesn't have to. It is not for internal-use-only items. Exactly! -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In message [EMAIL PROTECTED], Steven D'Aprano wrote: On Fri, 17 Oct 2008 23:04:52 +1300, Lawrence D'Oliveiro wrote: The right solution, of course, is fns = [(lambda x : lambda : x)(x) for x in range(10)] Only if by right solution you mean excessively verbose, confusing, and the sort of thing that makes even supporters of lambda cringe. Yes yes, it's just a factory function written with lambdas. It's still ugly and exactly the sort of thing that gives ammunition to lambda- haters. It's NOT ugly. It's EXACTLY the right sort of thing you do with lambda-expressions, going right back to Church. It's no more ugly than, say, parentheses in Lisp. :) -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Wed, Oct 15, 2008 at 9:43 PM, Aaron Castironpi Brady [EMAIL PROTECTED] wrote: On Oct 15, 11:33 pm, Steve Holden [EMAIL PROTECTED] wrote: Aaron Castironpi Brady wrote: [about how default argument behavior should, in his opinion, be changed] Say what you like. The language is as it is by choice. Were it, for some reason, to change we would then be receiving posts every week that didn't understand the *new* behavior. Sometimes people just have to learn to confirm with reality instead of requiring reality to confirm with their preconceptions. This is one such case. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ I am not convinced it should either stay or go, but it's hard to argue one way or the other about something so deeply entrenched. However, what are your thoughts, whatever the default behavior is, on a decorator that provides the alternative? That is, a decorator that either reevaluates default arguments each time when the language evaluates them once, or a decorator that evaluates arguments once, when the languages evaluates them each time? P.S. we would then be receiving posts every week that didn't understand the *new* behavior. That is not obvious and I don't know of any empirical evidence that entails it. Hard to search the standard library for that figure. Although primitive and likely somewhat flawed, you may find the statistics in the Compatibility Issues section of http://mail.python.org/pipermail/python-3000/2007-February/005704.html to be of interest. Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Chris Rebert: Although primitive and likely somewhat flawed, you may find the statistics in the Compatibility Issues section ofhttp://mail.python.org/pipermail/python-3000/2007-February/005704.html to be of interest. I am quite glad to see that I am not the only one that cares for such topic. And I think Guido is wrong here, but I can also see there's little hope in fixing this Python wart. We'll probably have to see and use another language to see this problem/bug fixed in some way (and maybe other issues added, no language is perfect). Python is now mature, being 15+ years old, so it's also rigid. Computer languages, just like living species, resist change, and usually you need a new language/species to fix some larger warts/bugs/design problems. Python3 fixes tons of problems of Python2.x, but it's almost a new language :-) Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Thu, 16 Oct 2008 17:05:40 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Steven D'Aprano wrote: On Thu, 09 Oct 2008 01:39:30 -0700, kenneth (a.k.a. Paolo) wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: No, it always contains the default argument because default values are created just ONE TIME http://effbot.org/pyfaq/why-are-default-values-shared-between- objects... Wow, it's a very dangerous behavior ... No, it's very *useful* behaviour. Can you give an example of how useful it is? Something worth the pain of newbies tripping over it every week? Did you read the effbot's explanation in the link above? He gives two examples, memoization and binding of locals. The second example is especially interesting, because that's also a Gotcha for newbies (not just noobs either...), and the solution to that specific gotcha is Python's use of define-time binding of default values. callbacks = [None]*4 for i in xrange(len(callbacks)): ... callbacks[i] = lambda s: '%d %s' % (i, s) ... for cb in callbacks: ... print cb('string') ... 3 string 3 string 3 string 3 string Newbies get confused by this almost as often as by the default value semantics, but the simplest solution to this gotcha is to use Python's default values: for i in xrange(len(callbacks)): ... callbacks[i] = lambda s, i=i: '%d %s' % (i, s) ... for cb in callbacks: ... print cb('string') ... 0 string 1 string 2 string 3 string If Python re-evaluated the default value i=i at runtime, the above would break. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 16, 1:05 am, Chris Rebert [EMAIL PROTECTED] wrote: On Wed, Oct 15, 2008 at 9:43 PM, Aaron Castironpi Brady [EMAIL PROTECTED] wrote: On Oct 15, 11:33 pm, Steve Holden [EMAIL PROTECTED] wrote: Aaron Castironpi Brady wrote: [about how default argument behavior should, in his opinion, be changed] Say what you like. The language is as it is by choice. Were it, for some reason, to change we would then be receiving posts every week that didn't understand the *new* behavior. Sometimes people just have to learn to confirm with reality instead of requiring reality to confirm with their preconceptions. This is one such case. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ I am not convinced it should either stay or go, but it's hard to argue one way or the other about something so deeply entrenched. However, what are your thoughts, whatever the default behavior is, on a decorator that provides the alternative? That is, a decorator that either reevaluates default arguments each time when the language evaluates them once, or a decorator that evaluates arguments once, when the languages evaluates them each time? P.S. we would then be receiving posts every week that didn't understand the *new* behavior. That is not obvious and I don't know of any empirical evidence that entails it. Hard to search the standard library for that figure. Although primitive and likely somewhat flawed, you may find the statistics in the Compatibility Issues section ofhttp://mail.python.org/pipermail/python-3000/2007-February/005704.html to be of interest. Cheers, Chris -- Follow the path of the Iguana...http://rebertia.com -- http://mail.python.org/mailman/listinfo/python-list I remember, I've seen it before. Are you proposing that the number of posts we'd receive about this feature is proportional to its frequency of usage? -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 16, 12:23 pm, Steven D'Aprano [EMAIL PROTECTED] cybersource.com.au wrote: On Thu, 16 Oct 2008 17:05:40 +1300, Lawrence D'Oliveiro wrote: In message [EMAIL PROTECTED], Steven D'Aprano wrote: On Thu, 09 Oct 2008 01:39:30 -0700, kenneth (a.k.a. Paolo) wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: No, it always contains the default argument because default values are created just ONE TIME http://effbot.org/pyfaq/why-are-default-values-shared-between- objects... Wow, it's a very dangerous behavior ... No, it's very *useful* behaviour. Can you give an example of how useful it is? Something worth the pain of newbies tripping over it every week? Did you read the effbot's explanation in the link above? He gives two examples, memoization and binding of locals. The second example is especially interesting, because that's also a Gotcha for newbies (not just noobs either...), and the solution to that specific gotcha is Python's use of define-time binding of default values. snip Newbies get confused by this almost as often as by the default value semantics, but the simplest solution to this gotcha is to use Python's default values: snip Both of those are shorthand notations and there are alternative ways to express both of them. The alternatives might even be more literal, that is, less idiomatic, in the language's tokens' semantics. For the first one, effbot says: 'You could use a global variable containing a dictionary instead of the default value; it’s a matter of taste'. You could also use an attribute of the function, which is an entry in func_dict. For the second one, it is more verbose, but you can add an enclosing lambda or def expression, and call it on the spot. I'll be honest: those are plusses, that is pros of the decision, but they aren't that strong. If Python re-evaluated the default value i=i at runtime, the above would break. Not with a mere extra lambda. The fact that a syntax is an opportunity to have a behavior does not imply that it should have one. The fact that newbies ask about these semantics doesn't imply that they'd ask about another one just as much. The fact that these semantics have these two uses, doesn't imply that the others don't have more. Immutable defaults behave identically in both. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: David C. Ullrich a écrit : In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: David C. Ullrich a écrit : (snip) Seems to me that people often site the important warning in the tutorial. Of course there's no reason anyone would bother going through the tutorial Indeed. No reason at all. - just for fun I looked in the official Python Reference Manual to see whether they're explicit about this or require the reader to figure it out from something else they say. There's a section titled 7.6 Function definitions. About halfway through that section there's a _bold face_ statement Default parameter values are evaluated when the function definition is executed., followed by an explanation of how that can lead to the sort of problem above. But there's no reason to read the reference manual neither. So I guess it _is_ awfully dangerous. They Hum... Who are they, exactly ? should really explain this aspect of the language's behavior to people who don't read the formal definition and also don't work through the tutorial. You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Yes. Also add don't read any books. Indeed. I think I started with some book As far as I'm concerned, I started with the FineManual(tm)'s tutorial. (snip) Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Yeps. But I don't think we derive the same conclusions from that point. Erm, I think maybe your irony detector needs a little calibration... [...] In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... I was worried someone might not realize I was being sarcastic, which is why I threw in this obvious impossibility If different users expect different - mostly incompatible - things, how would it be possible to have it working the way the user expect ? but I guess it wasn't enough. Should Python grow some telepathic features to guess the user's expectations and modifies itself to meet these expectations ?-) -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Thu, 16 Oct 2008 12:18:49 -0700, Aaron \Castironpi\ Brady wrote: [snip] If Python re-evaluated the default value i=i at runtime, the above would break. Not with a mere extra lambda. Not so. It has nothing to do with lambda, lambda just happens to be a convenient example. Here's the code I demonstrated: for i in xrange(len(callbacks)): ... callbacks[i] = lambda s, i=i: '%d %s' % (i, s) ... for cb in callbacks: ... print cb('string') ... 0 string 1 string 2 string 3 string At the end of the first loop, i == 3. If the default value i=i was re- evaluated each time the function was called, then i would get the value 3 each time, which is the same behaviour you get from the version with this: callbacks[i] = lambda s: '%d %s' % (i, s) Worse, because you're now relying on i as a global, it's subject to strange and mysterious bugs if you later change i and then call the callback. The fact that a syntax is an opportunity to have a behavior does not imply that it should have one. The fact that newbies ask about these semantics doesn't imply that they'd ask about another one just as much. The fact that these semantics have these two uses, doesn't imply that the others don't have more. Nowhere did I say that the one logically implies the other. I was asked for examples of how the current behaviour is useful, not to prove that the current behaviour logically follows from first principles. If you want to use a programming language where function default values are re- evaluated at runtime, you know where to find them. By the way, for the record I myself has found that behaviour useful on occasion. But that's easy to do with current Python: def spam(x, y=None): if y is None: # re-evaluate the default value at runtime y = get_some_other_value() return x + y So if you want that behaviour, you can get it. But if Python's semantics changed, then how would you implement today's semantics where the default is evaluated once only? I don't think you can. So Python's current semantics allows the behaviour you want, but in a slightly inconvenient form; but the re-evaluate-at-runtime semantics would prevent the behaviour I want completely. Immutable defaults behave identically in both. Not quite. To have immutable defaults behave identically, you would need to remove at least one more feature of Python: the ability to set a default value to an arbitrary expression, not just a literal. Why do you need to do this? This toy example demonstrates the problem if you don't: yy = 3 # immutable value bound to the name yy def spam(x, y=yy-1): return x + y will have the *expression* yy-1 re-evaluated when they call the function. That means that even though 2 is immutable, you can no longer rely on the default value being 2, or even existing at all. (What if I del yy at some point, then call the function?) So now to get the behaviour you desire, you not only have to change the way Python functions are implemented (and that will have a real and significant performance cost), but you also have to change the parser to only allow literals as default values. Note that there is absolutely nothing wrong with using an expression when setting default values. But you have to prohibit it, or else introduce unexpected behaviour which will trip up not just noobs but everybody. And then you'll have noobs writing in weekly asking why they can't write def foo(x, y=10**6) instead of y=1000. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 16, 7:54 pm, Steven D'Aprano [EMAIL PROTECTED] cybersource.com.au wrote: On Thu, 16 Oct 2008 12:18:49 -0700, Aaron \Castironpi\ Brady wrote: [snip] If Python re-evaluated the default value i=i at runtime, the above would break. Not with a mere extra lambda. Not so. It has nothing to do with lambda, lambda just happens to be a convenient example. Here's the code I demonstrated: for i in xrange(len(callbacks)): ... callbacks[i] = lambda s, i=i: '%d %s' % (i, s) ... for cb in callbacks: ... print cb('string') ... 0 string 1 string 2 string 3 string At the end of the first loop, i == 3. If the default value i=i was re- evaluated each time the function was called, then i would get the value 3 each time, which is the same behaviour you get from the version with this: callbacks[i] = lambda s: '%d %s' % (i, s) Worse, because you're now relying on i as a global, it's subject to strange and mysterious bugs if you later change i and then call the callback. The fact that a syntax is an opportunity to have a behavior does not imply that it should have one. The fact that newbies ask about these semantics doesn't imply that they'd ask about another one just as much. The fact that these semantics have these two uses, doesn't imply that the others don't have more. Nowhere did I say that the one logically implies the other. I was asked for examples of how the current behaviour is useful, not to prove that the current behaviour logically follows from first principles. If you want to use a programming language where function default values are re- evaluated at runtime, you know where to find them. By the way, for the record I myself has found that behaviour useful on occasion. But that's easy to do with current Python: def spam(x, y=None): if y is None: # re-evaluate the default value at runtime y = get_some_other_value() return x + y So if you want that behaviour, you can get it. But if Python's semantics changed, then how would you implement today's semantics where the default is evaluated once only? I don't think you can. So Python's current semantics allows the behaviour you want, but in a slightly inconvenient form; but the re-evaluate-at-runtime semantics would prevent the behaviour I want completely. Immutable defaults behave identically in both. Not quite. To have immutable defaults behave identically, you would need to remove at least one more feature of Python: the ability to set a default value to an arbitrary expression, not just a literal. Why do you need to do this? This toy example demonstrates the problem if you don't: yy = 3 # immutable value bound to the name yy def spam(x, y=yy-1): return x + y will have the *expression* yy-1 re-evaluated when they call the function. That means that even though 2 is immutable, you can no longer rely on the default value being 2, or even existing at all. (What if I del yy at some point, then call the function?) So now to get the behaviour you desire, you not only have to change the way Python functions are implemented (and that will have a real and significant performance cost), but you also have to change the parser to only allow literals as default values. Note that there is absolutely nothing wrong with using an expression when setting default values. But you have to prohibit it, or else introduce unexpected behaviour which will trip up not just noobs but everybody. And then you'll have noobs writing in weekly asking why they can't write def foo(x, y=10**6) instead of y=1000. -- Steven You're correct. I overstated the fact. Immutable defaults behave identically in both. Not quite. To have immutable defaults behave identically, you would need Immutable literal defaults behave identically in both. Obviously semantics would change if semantics change. Not with a mere extra lambda. Not so. It has nothing to do with lambda, lambda just happens to be a convenient example. Here's the code I demonstrated: snip What I stated is true, but I may not have stated it verbosely enough. callbacks= [ None ]* 3 for i in range( len( callbacks ) ): ... callbacks[ i ]= ( lambda i: ( lambda s: '%d %s' % (i, s) ) ) ( i ) ... for cb in callbacks: ... print cb('string') ... 0 string 1 string 2 string One extra lambda, called on the spot, as I stated. The 'callbacks' items do not rely on 'i' as a global; they contain a cell that refers to the contents of 'i' at the time they're called, that is, a entry in unique namespaces. When 'i' is rebound the next time through the loop or later, or deleted, they still have their values of it. Of course, if you're iterating over a collection of mutables, the namespaces get references to those. Then, if you mutate your iterator variable later, as opposed to rebind it, the namespace which contains it in a cell will see that change; they are one in the same object. Yours does that
Re: default value in __init__
In message [EMAIL PROTECTED], Steven D'Aprano wrote: On Thu, 09 Oct 2008 01:39:30 -0700, kenneth (a.k.a. Paolo) wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: No, it always contains the default argument because default values are created just ONE TIME http://effbot.org/pyfaq/why-are-default-values-shared-between-objects... Wow, it's a very dangerous behavior ... No, it's very *useful* behaviour. Can you give an example of how useful it is? Something worth the pain of newbies tripping over it every week? -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 15, 11:05 pm, Lawrence D'Oliveiro [EMAIL PROTECTED] central.gen.new_zealand wrote: In message [EMAIL PROTECTED], Steven D'Aprano wrote: On Thu, 09 Oct 2008 01:39:30 -0700, kenneth (a.k.a. Paolo) wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: No, it always contains the default argument because default values are created just ONE TIME http://effbot.org/pyfaq/why-are-default-values-shared-between-objects... Wow, it's a very dangerous behavior ... No, it's very *useful* behaviour. Can you give an example of how useful it is? Something worth the pain of newbies tripping over it every week? Not to be overly practical, but what kind of community push would van Rossum need in order to make a change, especially with 3.0 almost out? Even if everyone agrees, it seems too late even for the entire 3.x series, to be changing something that deeply embedded in not only _syntax_, but programmers' minds. I'd say a decorator would be a viable alternative, but even that would be hard to get into the language now. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 15, 11:33 pm, Steve Holden [EMAIL PROTECTED] wrote: Aaron Castironpi Brady wrote: [about how default argument behavior should, in his opinion, be changed] Say what you like. The language is as it is by choice. Were it, for some reason, to change we would then be receiving posts every week that didn't understand the *new* behavior. Sometimes people just have to learn to confirm with reality instead of requiring reality to confirm with their preconceptions. This is one such case. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ I am not convinced it should either stay or go, but it's hard to argue one way or the other about something so deeply entrenched. However, what are your thoughts, whatever the default behavior is, on a decorator that provides the alternative? That is, a decorator that either reevaluates default arguments each time when the language evaluates them once, or a decorator that evaluates arguments once, when the languages evaluates them each time? P.S. we would then be receiving posts every week that didn't understand the *new* behavior. That is not obvious and I don't know of any empirical evidence that entails it. Hard to search the standard library for that figure. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Aaron Castironpi Brady wrote: [about how default argument behavior should, in his opinion, be changed] Say what you like. The language is as it is by choice. Were it, for some reason, to change we would then be receiving posts every week that didn't understand the *new* behavior. Sometimes people just have to learn to confirm with reality instead of requiring reality to confirm with their preconceptions. This is one such case. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: David C. Ullrich a écrit : In article [EMAIL PROTECTED], kenneth [EMAIL PROTECTED] wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects .. . Wow, it's a very dangerous behavior ... Just to know, is this written somewhere in the python documentation or one has to discover it when his programs fails to work ;-) ? At least once a week someone discovers this problem, makes a post about it here, and then someone points to the spot in the documentation where it's explained. Seems to me that people often site the important warning in the tutorial. Of course there's no reason anyone would bother going through the tutorial Indeed. No reason at all. - just for fun I looked in the official Python Reference Manual to see whether they're explicit about this or require the reader to figure it out from something else they say. There's a section titled 7.6 Function definitions. About halfway through that section there's a _bold face_ statement Default parameter values are evaluated when the function definition is executed., followed by an explanation of how that can lead to the sort of problem above. But there's no reason to read the reference manual neither. So I guess it _is_ awfully dangerous. They should really explain this aspect of the language's behavior to people who don't read the formal definition and also don't work through the tutorial. You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Yes. Also add don't read any books. I think I started with some book - the book pointed out the surprise you get when you say L = [[0]] * 10 L[0][0] = 1 or something similar. I was probably surprised once by the mutable default parameter thing once but having understood that other example it wasn't hard to see what was happening. Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Basic Python is so transparent that you can start using it without reading anything, just looking at a few examples. _Because_ of that it's their responsibility to ensure that if you look at a few examples you then have a complete understanding of the language. In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
David C. Ullrich a écrit : In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: David C. Ullrich a écrit : (snip) Seems to me that people often site the important warning in the tutorial. Of course there's no reason anyone would bother going through the tutorial Indeed. No reason at all. - just for fun I looked in the official Python Reference Manual to see whether they're explicit about this or require the reader to figure it out from something else they say. There's a section titled 7.6 Function definitions. About halfway through that section there's a _bold face_ statement Default parameter values are evaluated when the function definition is executed., followed by an explanation of how that can lead to the sort of problem above. But there's no reason to read the reference manual neither. So I guess it _is_ awfully dangerous. They Hum... Who are they, exactly ? should really explain this aspect of the language's behavior to people who don't read the formal definition and also don't work through the tutorial. You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Yes. Also add don't read any books. Indeed. I think I started with some book As far as I'm concerned, I started with the FineManual(tm)'s tutorial. (snip) Well... How to say.. Is there any chance these people will read anything *at all* ? No. That's exactly the point! Yeps. But I don't think we derive the same conclusions from that point. Basic Python is so transparent that you can start using it without reading anything, just looking at a few examples. And immediatly fall into a well-known (and well-documented) gotcha - like forgetting to apply the call operator to function, using mutable default arguments, using mutable class attributes instead of instance attributes, etc, etc, etc... While it has been heavily publicized that Python is easy to get started with - which, AFAICT, seems to still be true for any programmer already having some experience *and* serious enough to actually _read_ that fucking manual -, it doesn't mean that, by the virtue of some extraterrestrial magic, one could master the language just reading a couple dummy examples. Learning a language requires some home work, period. _Because_ of that it's their who are they in this their ? responsibility to ensure that if you look at a few examples you then have a complete understanding of the language. I'm afraid I have to say this is *totally* utopic - except perhaps for the most braindead and limited language one could imagine. Heck, even Java - which has explicitely been designed for morons^Mdummies - would fail this test. How could a few examples provide complete understanding of attribute lookup rules, the descriptor protocol, metaclasses, iterators, and generator expression - just to name a few ? Granted, Python is easy to get started with. This doesn't mean anyone should expect it to work like any language XXX they already know. Every language has it's own pecularities, every language requires a serious learning effort, and Python is no exception here. FWIW, on most programming language-related newgroups, the only answer to such FAQs would be (at best) a raw RTFM. Not that I'd advertise such a behaviour here - this newsgroup is mostly newbies-friendly and I *really* appreciate it to be that way (and happily answer the same 101 questions year after year FWIW), but I really fail to see how anything more could be done for points that are 1/ clearly documented and 2/ reexplained here month after month. In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... If different users expect different - mostly incompatible - things, how would it be possible to have it working the way the user expect ? Should Python grow some telepathic features to guess the user's expectations and modifies itself to meet these expectations ?-) -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 14, 1:50 pm, Bruno Desthuilliers [EMAIL PROTECTED] wrote: David C. Ullrich a écrit : In article [EMAIL PROTECTED], Bruno Desthuilliers [EMAIL PROTECTED] wrote: snip (snip) snip In particular default parameters should work the way the user expects! The fact that different users will expect different things here is no excuse... If different users expect different - mostly incompatible - things, how would it be possible to have it working the way the user expect ? Should Python grow some telepathic features to guess the user's expectations and modifies itself to meet these expectations ?-) No. Just have a user community that only has one user. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
I would just like to add to the discussion that 4as a second year computer science undergraduate and I noticed the same issue with default arguments, but I was able to figure out the system of how (and why) python does it the way it does, without having to consult any documentation offline or online. If the person notices that arg={} is yielding an unexpecting result, the next step I would guess they would PROBABLY try setting arg=None and insert if arg==None: arg={} at the head of their method. It doesn't take a tremendous amount of cleverness power to try an alternate method that is logically equivalent to the intention. Daniel On Tue, Oct 14, 2008 at 10:25 PM, Dennis Lee Bieber [EMAIL PROTECTED]wrote: On Tue, 14 Oct 2008 20:50:13 +0200, Bruno Desthuilliers [EMAIL PROTECTED] declaimed the following in comp.lang.python: As far as I'm concerned, I started with the FineManual(tm)'s tutorial. Heh... whereas my introduction was the original O'Reilly Python text book, with a copy of the Amiga Python on disk... By the end of the week, I'd mashed together a rudimentary mail send utility in Python using ARexx for the client to spool queuing (needed as, at that time, Amiga email clients were very raw -- they required stand-alone external POP3 and SMTP programs to work with spool directories... And the first program I used for SMTP created a message per destination address and would block the entire outgoing spool if it couldn't connect to any particular address... The second program I tried did relay via ISP server -- but failed to transfer CC and BCC destinations!) I'm afraid I have to say this is *totally* utopic - except perhaps for the most braindead and limited language one could imagine. Heck, even Java - which has explicitely been designed for morons^Mdummies - would fail this test. How could a few examples provide complete understanding of attribute lookup rules, the descriptor protocol, metaclasses, iterators, and generator expression - just to name a few ? As far as I'm concerned, Java fails it even for experienced programmers... There is just too much overhead in just doing hello world that one NEEDS something like Eclipse just to start coding. If one wants to avoid reading documentation, my suggestion would be to install a version of old KK BASIC, circa 1970. -- WulfraedDennis Lee Bieber KD6MOG [EMAIL PROTECTED] [EMAIL PROTECTED] HTTP://wlfraed.home.netcom.com/ (Bestiaria Support Staff: [EMAIL PROTECTED]) HTTP://www.bestiaria.com/ -- http://mail.python.org/mailman/listinfo/python-list -- Daniel da Silva (240) 678 - 4686 GSFC, GES-DISC 610.2 University of Maryland -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Fri, 10 Oct 2008 06:20:35 -0700, bearophileHUGS wrote: I don't think simply re-executing the default argument expression on each call works either: that would confuse at least as many people as the current system. May I ask you why? I think I don't agree, but I am not sure. x = 100 def foo(a, b=x): return a+b first = foo(1) x = 101 second = foo(1) assert first == second I think people will be rightly surprised that this fails. It would be possible, but extremely annoying to limit default arguments to being literal constants, This is a possible solution, beside re-executing the default argument expression on each call. That's no solution at all, because default arguments should not be limited to literal constants. That's unacceptable in my opinion. unless you invent some kind of scheme for declaring that a type is safe to use as a default argument. Well, it seems functional-style programming may become more common in the future, and seeing languages like Scala, etc, maybe it can be useful to add to Python some way to define immutable classes (in an explicit way). Maybe subclasses of Immutable? You're still assuming that the behaviour is a bug. It's not, it's a feature. Even if you could change the behaviour of default arguments we would still get equivalent regular questions from the people who initialise class attributes with lists or dictionaries. I have seen professional programmers too use class attributes instead of instance ones... That's only a mistake if you don't mean to use class attributes instead of instance attributes. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Thu, 09 Oct 2008 01:39:30 -0700, kenneth (a.k.a. Paolo) wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between- objects... Wow, it's a very dangerous behavior ... No, it's very *useful* behaviour. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 10, 12:30 pm, Duncan Booth [EMAIL PROTECTED] wrote: [EMAIL PROTECTED] wrote: I don't think simply re-executing the default argument expression on each call works either: that would confuse at least as many people as the current system. May I ask you why? I think I don't agree, but I am not sure. (snip) I wonder whether it is the way the default argument expressions are embedded inside the function that causes the confusion? If for example default arguments were defined like this: class C: @default(d={}) def __init__(self, i=10, d): self.d = d self.i = i would moving the expression before the 'def' make people less inclined to be suprised that the object is shared? You could of course define a wrapper to do call-time assignment: @calltime( d= dict, e= tuple ) def foo( self, d, e ): If this decorator appeared in the standard library, newbies would be able to stumble upon it. I don't think either semantic is more obvious from the syntax alone. It could mean either thing just as reasonably, and if Python defined the opposite, we'd be getting opposite complaints. On one hand, note that the return statement does not follow the same convention: def f(): return [ 0, 1 ] ... f().append( 2 ) f() [0, 1] It constructs a new object each time. In light of this, the burden of proof could even fall on Python for the inconsistency. That is, assuming that it's well- and always defined. -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 11, 4:41 am, Steven D'Aprano [EMAIL PROTECTED] cybersource.com.au wrote: On Fri, 10 Oct 2008 06:20:35 -0700, bearophileHUGS wrote: snip I have seen professional programmers too use class attributes instead of instance ones... That's only a mistake if you don't mean to use class attributes instead of instance attributes. Off topic: That gives me an idea for an interesting technique. class Foo( HasInstanceVars ): class InstanceVars: x= 0 y= None z= [ 0, 1 ] The __init__ method in HasInstanceVars adds any InstanceVars members to the instance members. It's not terribly different than using __init__-- slightly slower, slightly clearer. It could even include a '__initvars__' variable which adds constructor parameters by name to the instance. It's marginally problematic how to create new objects each time Foo is instantiated. You could require factories, pickle- unpickle the contents, require 'deepcopy' compatibility, execute a string, or call a function which uniquely executes the class statement. foo= Foo() foo.x+= 1 foo2= Foo() foo2.x 0 foo.x 1 -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
[EMAIL PROTECTED] wrote: Bruno Desthuilliers: You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Are there ways to change how Python3 manages arguments and functions, to remove this antifeature of Python, avoiding this common mistake done by every newbie? I don't care if it reduces the performance of Python a little. You can't just copy the default values on every call: you would still get people confused by the semantics whether you did a shallow or deep copy or as now no copy. I don't think simply re-executing the default argument expression on each call works either: that would confuse at least as many people as the current system. It would be possible, but extremely annoying to limit default arguments to being literal constants, or slightly less drastically limit them to being of types known to be immutable. Of course that blocks you from using any user defined types unless you invent some kind of scheme for declaring that a type is safe to use as a default argument. Another option might just be to generate a warning the first time a program uses a not obviously immutable default. I think in this situation the best solution is to expect people to learn to use the language, and accept that those people who don't RTFM will keep on asking here. Even if you could change the behaviour of default arguments we would still get equivalent regular questions from the people who initialise class attributes with lists or dictionaries. -- Duncan Booth http://kupuguy.blogspot.com -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
David C. Ullrich a écrit : In article [EMAIL PROTECTED], kenneth [EMAIL PROTECTED] wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects.. . Wow, it's a very dangerous behavior ... Just to know, is this written somewhere in the python documentation or one has to discover it when his programs fails to work ;-) ? At least once a week someone discovers this problem, makes a post about it here, and then someone points to the spot in the documentation where it's explained. Seems to me that people often site the important warning in the tutorial. Of course there's no reason anyone would bother going through the tutorial Indeed. No reason at all. - just for fun I looked in the official Python Reference Manual to see whether they're explicit about this or require the reader to figure it out from something else they say. There's a section titled 7.6 Function definitions. About halfway through that section there's a _bold face_ statement Default parameter values are evaluated when the function definition is executed., followed by an explanation of how that can lead to the sort of problem above. But there's no reason to read the reference manual neither. So I guess it _is_ awfully dangerous. They should really explain this aspect of the language's behavior to people who don't read the formal definition and also don't work through the tutorial. You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Well... How to say.. Is there any chance these people will read anything *at all* ? -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Bruno Desthuilliers: You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Are there ways to change how Python3 manages arguments and functions, to remove this antifeature of Python, avoiding this common mistake done by every newbie? I don't care if it reduces the performance of Python a little. Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Duncan Booth: You can't just copy the default values on every call: you would still get people confused by the semantics whether you did a shallow or deep copy or as now no copy. I think I agree. I don't think simply re-executing the default argument expression on each call works either: that would confuse at least as many people as the current system. May I ask you why? I think I don't agree, but I am not sure. It would be possible, but extremely annoying to limit default arguments to being literal constants, This is a possible solution, beside re-executing the default argument expression on each call. unless you invent some kind of scheme for declaring that a type is safe to use as a default argument. Well, it seems functional-style programming may become more common in the future, and seeing languages like Scala, etc, maybe it can be useful to add to Python some way to define immutable classes (in an explicit way). Maybe subclasses of Immutable? Another option might just be to generate a warning the first time a program uses a not obviously immutable default. I don't like this solution much. Even if you could change the behaviour of default arguments we would still get equivalent regular questions from the people who initialise class attributes with lists or dictionaries. I have seen professional programmers too use class attributes instead of instance ones... Well, you can't create a fool-proof language that is useful too, but in a language that is designed for new programmers too, like Python, and that doesn't put the running speed as its most important feature, then I think patching the most known and common pitfalls/traps is useful, even if you can't patch them all (without turning the language into something useless). Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Fri, Oct 10, 2008 at 4:36 AM, [EMAIL PROTECTED] wrote: Bruno Desthuilliers: You mean : to people that don't bother reading the FineManual *nor* searching the newsgroup / ML archives ? Are there ways to change how Python3 manages arguments and functions, to remove this antifeature of Python, avoiding this common mistake done by every newbie? I don't care if it reduces the performance of Python a little. The general idea been discussed ad-nauseum on the list several times before, including just 2 months ago. See e.g.: [Python-3000] default argument surprises http://mail.python.org/pipermail/python-3000/2008-August/014658.html [Python-ideas] proto-PEP: Fixing Non-constant Default Arguments http://mail.python.org/pipermail/python-ideas/2007-January/000121.html [Python-3000] pre-PEP: Default Argument Expressions http://mail.python.org/pipermail/python-3000/2007-February/005704.html Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
[EMAIL PROTECTED] wrote: I don't think simply re-executing the default argument expression on each call works either: that would confuse at least as many people as the current system. May I ask you why? I think I don't agree, but I am not sure. My thought (which may well be wrong) is that people would still expect the default argument expression to use the values of variables at the time when the function is defined, not the values at the point of calling it. e.g. in this hypothetical universe: y = 0 def f(x=y): return x*x y = 1 f() 1 would certainly be suprising to anyone used to the current behaviour and I think would also suprise anyone who hadn't read the manual in sufficient details. We already get people asking why code like this doesn't return 3: fns = [ lambda: x for x in range(10) ] fns[3]() 9 i.e. they expect the variable lookup to be done at function definition time rather than function call time. This implies to me that some people are going to get confused whichever way round these things happen although perhaps it is the behaviour of default arguments that makes them expect this. As an aside, making this change to default arguments would mean the solution usually proposed to the function scoping question above would no longer work: fns = [ lambda y=x: y for x in range(10) ] fns[3]() 3 I wonder whether it is the way the default argument expressions are embedded inside the function that causes the confusion? If for example default arguments were defined like this: class C: @default(d={}) def __init__(self, i=10, d): self.d = d self.i = i would moving the expression before the 'def' make people less inclined to be suprised that the object is shared? -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
Chris Rebert: The general idea been discussed ad-nauseum on the list several times before, including just 2 months ago. See e.g.: Okay, it can't be fixed then. Bye and thank you, bearophile -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
See Pitfall #5 on http://zephyrfalcon.org/labs/python_pitfalls.html It also applies to dictionaries (and sets, any mutable object really). On Thu, Oct 9, 2008 at 1:03 AM, kenneth [EMAIL PROTECTED] wrote: Dear all, I have encountered this weird problem. I have a class definition with an __init__ argument 'd' which defaults to {}. This argument is put in the 'self.d' attribute at initialization I create two independent instances of this class; the code is as follows. class C: def __init__(self, i=10, d = {}): Change 'd = {}' to 'd=None' Add the line: if d is None: d = {} Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com self.d = d self.i = i def get(self): print print self.d def set(self, dval, ival): self.d.update(dval) self.i+=ival c1=C() c1.set({'one':1},3) c1.get() del c1 c2=C() c2.set({'two':2},4) c2.get() If I run the code I obtain: {'one': 1} {'two': 2, 'one': 1} It seems that the 'self.d' argument of the second instance is the same of the 'self.d' of the first (deleted!) instance. Running the code in a debugger I discovered that, when I enter the __init__ at the second initialization, before doing self.d = d the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? Thanks in advance for any help, Paolo -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME. http://effbot.org/pyfaq/why-are-default-values-shared-between-objects.htm -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Thu, Oct 9, 2008 at 1:39 AM, kenneth [EMAIL PROTECTED] wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects... Wow, it's a very dangerous behavior ... Just to know, is this written somewhere in the python documentation or one has to discover it when his programs fails to work ;-) ? It's mentioned in the tutorial (note the Important warning): http://docs.python.org/tutorial/controlflow.html#default-argument-values Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com Paolo -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects... Wow, it's a very dangerous behavior ... Just to know, is this written somewhere in the python documentation or one has to discover it when his programs fails to work ;-) ? Paolo -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
kenneth a écrit : On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects... Wow, it's a very dangerous behavior ... Well, that's usually something you only have to learn once - then you know !-) -- http://mail.python.org/mailman/listinfo/python-list
Re: default value in __init__
In article [EMAIL PROTECTED], kenneth [EMAIL PROTECTED] wrote: On Oct 9, 10:14 am, Christian Heimes [EMAIL PROTECTED] wrote: kenneth wrote: the 'd' variable already contains the 'self.d' value of the first instance and not the default argument {}. Am I doing some stupid error, or this is a problem ? No, it always contains the default argument because default values are created just ONE TIME.http://effbot.org/pyfaq/why-are-default-values-shared-between-objects.. . Wow, it's a very dangerous behavior ... Just to know, is this written somewhere in the python documentation or one has to discover it when his programs fails to work ;-) ? At least once a week someone discovers this problem, makes a post about it here, and then someone points to the spot in the documentation where it's explained. Seems to me that people often site the important warning in the tutorial. Of course there's no reason anyone would bother going through the tutorial - just for fun I looked in the official Python Reference Manual to see whether they're explicit about this or require the reader to figure it out from something else they say. There's a section titled 7.6 Function definitions. About halfway through that section there's a _bold face_ statement Default parameter values are evaluated when the function definition is executed., followed by an explanation of how that can lead to the sort of problem above. So I guess it _is_ awfully dangerous. They should really explain this aspect of the language's behavior to people who don't read the formal definition and also don't work through the tutorial. Paolo -- David C. Ullrich -- http://mail.python.org/mailman/listinfo/python-list