Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > default value for __init__ doesn't work

Reply
Thread Tools

default value for __init__ doesn't work

 
 
人言落日是天涯,望极天涯不见家
Guest
Posts: n/a
 
      09-11-2010
Please look at below code snippet:
class test():
def __init__(self, a, dic={}):
self.a = a
self.dic = dic
print('__init__ params:',a, dic)

def get(self):
self.dic[1] = 2
self.dic[4] = 5

def foo():
print('in foo function')
bar = test(1)
bar.get()

if __name__ == '__main__':
foo()
foo()
-----------------------
Result:
in foo function
__init__ params: 1 {}
in foo function
__init__ params: 1 {1: 2, 4: 5}

But my expect result is :
in foo function
__init__ params: 1 {}
in foo function
__init__ params: 1 {}

it seems that the default value for dic doesn't work on the second
call for the class test.
It's wired. Who can give a explaination for this scenario?
 
Reply With Quote
 
 
 
 
Benjamin Kaplan
Guest
Posts: n/a
 
      09-11-2010
On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 <(E-Mail Removed)> 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 ==
...
 
Reply With Quote
 
 
 
 
人言落日是天涯,望极天涯不见家
Guest
Posts: n/a
 
      09-11-2010
On Sep 11, 1:14*pm, Benjamin Kaplan <(E-Mail Removed)> wrote:
> On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 <(E-Mail Removed)> 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.
 
Reply With Quote
 
人言落日是天涯,望极天涯不见家
Guest
Posts: n/a
 
      09-11-2010
On Sep 11, 1:55*pm, 人言落日是天涯,望极天涯不见家 <(E-Mail Removed)> wrote:
> On Sep 11, 1:14*pm, Benjamin Kaplan <(E-Mail Removed)> wrote:
>
>
>
> > On Sat, Sep 11, 2010 at 12:38 AM, 人言落日是天涯,望极天涯不见家 <(E-Mail Removed)> 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!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Should one always add super().__init__() to the __init__? Ramchandra Apte Python 17 09-30-2012 12:04 PM
default value in __init__ kenneth Python 38 10-20-2008 11:55 AM
super(...).__init__() vs Base.__init__(self) Kent Johnson Python 7 02-12-2006 08:59 PM
Default argument to __init__ netvaibhav@gmail.com Python 5 10-10-2005 05:06 PM
__new__ does not call __init__ as described in descrintro.html (WAS:Can __new__ prevent __init__ from being called?) Steven Bethard Python 2 02-16-2005 06:50 AM



Advertisments