[Tutor] : unexpected behavior with assignment in __init__
Kent Johnson
kent37 at tds.net
Wed Jan 25 12:07:46 CET 2006
Orri Ganel wrote:
> Hello all,
> I was just messing around with a suggestion w chun (wescpy at gmail
> dot com) gave (to make a class that handles time, ie:
>
>> >> import myTime
>> >> c = myTime.myTime(10,30)
>> >> print c
> 10:30
>> >> d = myTime.myTime(8,45)
>> >> print c + d
> 19:15
>
> etc), and I was trying to make it like the str class in that, by
> default, when you str() a string, it returns the same object. I tried
> to do this with the following (irrelevant code removed), but it didn't
> work, despite original indications to the contrary, and I'm not sure I
> understand why:
>
> >>> class stime:
> def __init__(self, minutes, seconds=None):
> if seconds is None:
> if minutes.__class__ is stime:
> print minutes, type(minutes), minutes.__class__, id(minutes)
> self = minutes
> print self, type(self), self.__class__, id(self)
> def __repr__(self):
> return str(self)
> def __str__(self):
> return "%02d:%02d" % (self.minutes, self.seconds)
Assigning to self in __init__() just changes the value of the local
variable, it has no effect outside the method; inside a method, self is
just a method parameter, nothing more. There is some magic that gives
self its value for the call.
When __init__() is called the new instance has already been created, you
are just initializing its state, not creating the object. You can do
what you want by defining stime.__new__(). __new__() is responsible for
actually creating a new object. You still have to check for an stime
instance in __init__() because __init__() will be called even when
__new__() returns an existing instance.
Here is a simplified example:
>>> class stime(object):
... def __new__(cls, value):
... if isinstance(value, cls):
... return value
... return object.__new__(cls, value)
... def __init__(self, value):
... print 'stime.__init__', value
... if isinstance(value, stime):
... return
... self.value = value
...
>>> a=stime(3)
stime.__init__ 3
>>> a
<__main__.stime object at 0x00A32E90>
>>> b=stime(a)
stime.__init__ <__main__.stime object at 0x00A32E90>
>>> b
<__main__.stime object at 0x00A32E90>
>>> a.value
3
>>> b.value
3
>>> a is b
True
Kent
>
> >>> a = stime(10,3)
> >>> b = stime(a)
> 10:03 <type 'instance'> __main__.stime 12858832
> 10:03 <type 'instance'> __main__.stime 12858832
> >>> # so, it appears to work, because it prints the same id both times.
> however,
> # . . .
> >>> id(a)
> 12858832
> >>> id(b)
> 12858792
> >>> # they're not the same anymore! and that's not all:
> >>> a
> 10:03
> >>> b
>
> Traceback (most recent call last):
> File "<pyshell#163>", line 1, in -toplevel-
> b
> File "C:/Documents and Settings/Cookie/Desktop/stime.py", line 20, in
> __repr__
> return str(self)
> File "C:/Documents and Settings/Cookie/Desktop/stime.py", line 22, in
> __str__
> return "%02d:%02d" % (self.minutes, self.seconds)
> AttributeError: stime instance has no attribute 'minutes'
>
> So, not only do the two variables not refer to the same object after
> exiting __init__, but b is now a broken stime instance. Anyone know
> what's going on?
>
> Thanks in advance,
> Orri
>
> --
> Email: singingxduck AT gmail DOT com
> AIM: singingxduck
> Programming Python for the fun of it.
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
More information about the Tutor
mailing list