如何在__init__()中用不同对象替换实例?
我在ClassA里调用一个构造函数,想要在满足某个条件时,得到的对象是另一个类(ClassB)的实例。我试着在__init__()里替换第一个参数(下面例子中的'self'),但是这样做似乎没有达到我想要的效果。
在主程序中:
import ClassA
my_obj = ClassA.ClassA(500)
# unfortunately, my_obj is a ClassA, but I want a ClassB!
在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
在ClassB/__init__.py里:
class ClassB:
pass
3 个回答
不要搞错构造函数的用途:应该使用工厂函数。调用一个类的构造函数却返回了另一个类的实例,这样会让人很困惑。
我建议你使用工厂模式来解决这个问题。举个例子:
def get_my_inst(the_number):
if the_number > 10:
return ClassB(the_number)
else:
return ClassA(the_number)
class_b_inst = get_my_inst(500)
class_a_inst = get_my_inst(5)
你需要用到 __new__()
这个方法。(如果你在用 Python 2,还得把它变成新式类,也就是要继承 object
。)
class ClassA(object):
def __new__(cls,theirnumber):
if theirnumber > 10:
# all big numbers should be ClassB objects:
return ClassB.ClassB(theirnumber)
else:
# numbers under 10 are ok in ClassA.
return super(ClassA, cls).__new__(cls, theirnumber)
__new__()
是在创建类的过程中先执行的,之后才会执行 __init__()
。简单来说,__new__()
是用来真正创建新实例的,而 __init__()
则是用来初始化这个实例的属性。这就是为什么你可以用 __new__()
来改变创建的对象类型,但不能用 __init__()
:一旦 __init__()
开始执行,那个对象已经创建好了,类型就不能再改了。(其实是可以的,但那就涉及到一些比较复杂的 Python 技巧了。)你可以查看文档了解更多。
不过在这种情况下,我觉得用工厂函数更合适,像这样:
def thingy(theirnumber):
if theirnumber > 10:
return ClassB.ClassB(theirnumber)
else:
return ClassA.ClassA(theirnumber)
顺便提一下,如果你像我上面那样使用 __new__()
,如果返回的是 ClassB
,那么你在 ClassA
中写的 __init__()
方法是不会被调用的!当你在 ClassA.__new__()
中构造 ClassB
的实例时,它自己的 __init__()
方法(ClassB.__init__()
)会在那时被执行,所以可以理解为什么 Python 不会在同一个对象上再运行一个无关的 __init__()
方法。不过这可能会让人有点困惑,这也是支持使用工厂函数的一种理由。