I am calling a constructor in ClassA and want to have the resulting object be of a different class (ClassB) if a certain condition is met. I’ve tried replacing the first argument to __init__() (‘self’ in the example below) within __init__() but it doesn’t seem to do what I want.
in main:
import ClassA
my_obj = ClassA.ClassA(500)
# unfortunately, my_obj is a ClassA, but I want a ClassB!
in ClassA/__init__.py:
import ClassB
class ClassA:
def __init__(self,theirnumber):
if(theirnumber > 10):
# all big numbers should be ClassB objects:
self = ClassB.ClassB(theirnumber)
return
else:
# numbers under 10 are ok in ClassA.
return
in ClassB/__init__.py:
class ClassB:
pass
You need
__new__()for that. (And you also need to make it a new-style class, assuming you’re using Python 2, by subclassingobject.)__new__()runs as part of the class instantiation process before__init__(). Basically__new__()is what actually creates the new instance, and__init__()is then called to initialize its properties. That’s why you can use__new__()but not__init__()to alter the type of object created: once__init__()starts, the object has already been created and it’s too late to change its type. (Well… not really, but that gets into very arcane Python black magic.) See the documentation.In this case, though, I’d say a factory function is more appropriate, something like
By the way, note that if you do what I did with
__new__()above, if aClassBis returned, the__init__()method you wrote inClassAwill not be called on theClassBinstance! When you construct theClassBinstance insideClassA.__new__(), its own__init__()method (ClassB.__init__()) will be run at that point, so hopefully it makes sense that Python shouldn’t run another unrelated__init__()method on the same object. But this can get kind of confusing, which is probably another argument in favor of the factory function approach.