Issue537450
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2002-03-31 17:23 by jacobs99, last changed 2022-04-10 16:05 by admin. This issue is now closed.
Files | ||||
---|---|---|---|---|
File name | Uploaded | Description | Edit | |
diff-init | jacobs99, 2002-04-01 14:17 | Patch to typeobject.c |
Messages (6) | |||
---|---|---|---|
msg10091 - (view) | Author: Kevin Jacobs (jacobs99) | Date: 2002-03-31 17:23 | |
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. |
|||
msg10092 - (view) | Author: Kevin Jacobs (jacobs99) | Date: 2002-04-01 14:17 | |
Logged In: YES user_id=459565 Patch attached. Passes Python descr tests and our extremely comprehensive in-house test suite that tortures new-style classes in fairly gruesome ways. Note: The ugly test to avoid calling tp_init on type(x) calls was intentionally left in the code, to handle the case of calling type(type). It is very likely that the test is now unnecessary and can be removed since calling tp_init on type objects should be safe, because they do not implement their own tp_init. However, for the sake of simplicity, I'm going to leave this additional cleanup to Guido, or others. |
|||
msg10093 - (view) | Author: Tim Peters (tim.peters) * | Date: 2002-04-01 14:43 | |
Logged In: YES user_id=31435 Thanks, Kevin! Assigned to Guido, under the theory that it lands on his plate sooner or later, and better sooner. |
|||
msg10094 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2002-04-06 00:17 | |
Logged In: YES user_id=6380 I think Kevin's suggestion is about right, but I'd like to add one twist: C.__new__ could return an instance of a subclass of C, and in that case I think that the __init__ should still be called. I'll see about a proper fix. It's a clear semantic change, so I don't want to change this in 2.2.x. |
|||
msg10095 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2002-04-06 01:05 | |
Logged In: YES user_id=6380 Fixed in CVS, using PyType_IsSubtype(obj->type, type). Note that the exception for type(x) is still needed (the test suite could have told you that). |
|||
msg10096 - (view) | Author: Guido van Rossum (gvanrossum) * | Date: 2002-10-07 18:09 | |
Logged In: YES user_id=6380 Given Kevin's plea, I've backported this to Python 2.2.2b1, with the caveat that I may undo it if problems arise during the (short!) beta release time. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-10 16:05:10 | admin | set | github: 36360 |
2002-03-31 17:23:27 | jacobs99 | create |