[Python-bugs-list] [ python-Bugs-537450 ] Improper object initialization
noreply@sourceforge.net
noreply@sourceforge.net
Sun, 31 Mar 2002 09:23:27 -0800
Bugs item #537450, was opened at 2002-03-31 12:23
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=537450&group_id=5470
Category: Type/class unification
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Kevin Jacobs (jacobs99)
Assigned to: Nobody/Anonymous (nobody)
Summary: Improper object initialization
Initial Comment:
The descr tutorial specifies this rule:
__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.
I believe that this rule adds an unnecessary wart to
the language, since it is not appropriate to call
__init__, especially with the same arguments as
__new__ on an 'unexpected' class returned by __new__.
It is simple enough to check that the resulting class
is an instance of the expected class and to only then
call __init__. Otherwise, it should be assumed that
__new__ is returning a fully constructed instance of
another class. In the rare and obscure case that one
does wish to call __init__ on an object of a different
class, then it may be done manually from within
__new__.
So basically, my argument is for explicit versus
implicit semantics. If __new__(cls) returns an
instance where type(instance) is not cls, then
__init__ should not be called implicitly. The
burden should be on the programmer to explicitly
ensure that the object is properly constructed.
Here is an example where the current rule results
in confusing and apparently random behavior
(if one doesn't have initimate knowledge of the
Python implementation, that is):
class Foo(object):
def __new__(cls, x):
if x == 0:
return [1,2,3]
if x == 1:
return 1
if x == 2:
return (1,2,3)
if x == 3:
return '1'
if x == 4:
return {1:1,2:2,3:3}
else:
return super(cls, Foo).__new__(cls)
for i in range(6):
try:
print 'Foo(%d) =' % i,Foo(i)
except:
print 'Foo(%d) failed' % i
Which under Python 2.2 results in the following output:
Foo(0) failed
Foo(1) = 1
Foo(2) = (1, 2, 3)
Foo(3) = 1
Foo(4) failed
Foo(5) = <__main__.Foo object at 0x8147f54>
Under the proposed new rule, the output would be
much more sensible:
Foo(0) = [1,2,3]
Foo(1) = 1
Foo(2) = (1, 2, 3)
Foo(3) = 1
Foo(4) = {1:1,2:2,3:3}
Foo(5) = <__main__.Foo object at 0x8147f54>
If there is agreement on this issue, I will submit
a very simple patch to address this.
----------------------------------------------------------------------
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=537450&group_id=5470