""" __new__ must return an object. There's nothing that requires that it return a new object that is an instance of its class argument, although that is the convention. If you return an existing object, the constructor call will still call its __init__ method. If you return an object of a different class, its __init__ method will be called. """
The quote implies that when I call carol, b.__init__ should be called. However, this does not seem to be the case (see code below). What am I not understanding? Shouldn't the interpreter call b.__init__ when b is returned from carol.__new__?
James
py> class bob(object): ... def __init__(self): ... print self.x ... x = 2 ... py> class carol(object): ... def __new__(cls): ... return b ... py> b=bob() py> b.x 2 py> c = carol() # should print "2" py> c <__main__.bob object at 0x404333cc>
-- James Stroud UCLA-DOE Institute for Genomics and Proteomics Box 951570 Los Angeles, CA 90095
> The quote implies that when I call carol, b.__init__ should be called. > However, this does not seem to be the case (see code below). What am I > not > understanding? Shouldn't the interpreter call b.__init__ when b is > returned > from carol.__new__?
> James
> py> class bob(object): > ... def __init__(self): > ... print self.x > ... x = 2 > ... > py> class carol(object): > ... def __new__(cls): > ... return b > ... > py> b=bob() > py> b.x > 2 > py> c = carol() # should print "2" > py> c > <__main__.bob object at 0x404333cc>
It seems to produce the output you expected for me (Python 2.4.1 on Windows XP), but this has nothing to do with "carol". How are bob and carol related?
Code:
class bob(object): def __init__(self): print self.x x = 2
class carol(object): def __new__(cls): return b b=bob() print b.x c = carol() c
Output:
2 2
This code produces the same output:
class bob(object): def __init__(self): print self.x x = 2 ## class carol(object): ## def __new__(cls): ## return b b=bob() print b.x ## c = carol() ##c
I am interested in the underlying subject but think your code was mispasted into the e-mail...
> """ > __new__ must return an object. There's nothing that requires that it > return a new object that is an instance of its class argument, although > that is the convention. If you return an existing object, the constructor > call will still call its __init__ method. If you return an object of a > different class, its __init__ method will be called. > """
> The quote implies that when I call carol, b.__init__ should be called. > However, this does not seem to be the case (see code below). What am I not > understanding? Shouldn't the interpreter call b.__init__ when b is > returned from carol.__new__?
Here's what "Python in a Nutshell" (p84) says:
""" Each new-style class has a static method named __new__. When you call C(*args, **kwds) to create a new instance of a new-style class C, Python invokes C.__new__(C, *args, **kwds). Python uses __new__'s return value x as the newly created instance. Then, Python calls C.__init__(x, *args, **kwds), but only when x is indeed an instance of C (otherwise, x's state is as __new__ had left it). Thus, for a new-style class C, the statement x=C(23) is equivlent to the following code:
x = C.__new__(C, 23) if isinstance(x, C): C.__init__(x, 23) """
If the following code says what I think it does
class A(object): def __init__(self): print "init A" def __new__(cls): return b
class B(A): def __init__(self): print "init B"
b = object.__new__(B)
print "---" A() # prints 'init B' A.__init__(b) # prints 'init A' print "---" b = 42 A() # prints nothing
the "Nutshell" example should be changed to
x = C.__new__(C, 23) if isinstance(x, C): x.__init__(23)
to comply with the current implementation (I used Python 2.4).
> is as __new__ had left it). Thus, for a new-style class C, the statement > x=C(23) is equivlent to the following code:
> x = C.__new__(C, 23) > if isinstance(x, C): C.__init__(x, 23) ... > the "Nutshell" example should be changed to
> x = C.__new__(C, 23) > if isinstance(x, C): x.__init__(23)
> to comply with the current implementation (I used Python 2.4).
Hmmm -- not quite, because in the new-style object model special methods are taken from the type, NOT from the instance as the latter is saying. E.g, if you change class B into:
class B(A): def __init__(self): print "init B" def f(): print 'from instance' self.__init__ = f
you'll see that while b.__init__() would print 'from instance', instantiating A will not. I think the right correction to the Nutshell is therefore:
x = C.__new__(C, 23) if isinstance(x, C): type(x).__init__(x, 23)
and this is how I plan to have it in the 2nd edition.
> """ > __new__ must return an object. There's nothing that requires that it return a > new object that is an instance of its class argument, although that is the > convention. If you return an existing object, the constructor call will still > call its __init__ method. If you return an object of a different class, its > __init__ method will be called. > """
Any reason why you're looking at 2.2 documentation when you're running 2.3?
Anyway, the current docs corrected this mistake[1]
""" If __new__() returns an instance of cls, then the new instance's __init__() method will be invoked like "__init__(self[, ...])", where self is the new instance and the remaining arguments are the same as were passed to __new__().
If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked. """