我将首先编写代码,然后详细解释我要实现的目标,因为这样做比较容易:
global child_selector
class Base(object):
def __init__(self):
self.extended_name = self.name + '_Base'
class Child1(Base):
def __init__(self):
super(Child1, self).__init__()
def print_my_name(self):
print 'I am ChildOne'
class Child2(Base):
def __init__(self):
super(Child2, self).__init__()
def print_my_name(self):
print 'I am ChildTwo'
class ChildAsBaseSelector(object):
def __new__(cls):
if child_selector == 1:
return Child1()
elif child_selector == 2:
return Child2()
else:
print 'No child selected'
现在如果我创建一个从Child1或Child2继承的类姓名作为实例变量,一切都按预期工作:
class Testing1(Child1):
def __init__(self):
self.name = 'Testing1'
super(Testing1, self).__init__()
a = Testing1()
a.print_my_name() # 'I am ChlidOne'
print a.extended_name # 'Testing1_Base'
但是如果我创建另一个类,它将直接从ChildAsBaseSelector()继承,那么事情就变得可疑了:
class Testing2(ChildAsBaseSelector):
def __init__(self):
self.name = 'Testing2'
super(Testing2, self).__init__()
child_selector = 1
a = Testing2()
# Will raise AttributeError: 'Child1' object has no attribute 'name'
在阅读了关于“\uuuu new\uuuuuuuuuuuuo()”的python文档之后,我认为问题是因为:“如果\uuuu new\uuuuuuuuo()没有返回cls的实例,那么新实例的\uuuu init\uuuuuuuuo()方法将不会被调用。”这并没有真正的帮助,因为我不知道如何“修复它”。你知道吗
我也知道我可以这样做:
if child_selector == 1:
ChildAsBaseSelector = Child1
if child_selector == 2:
ChildAsBaseSelector = Child2
而不是直接从ChildAsBaseSelector继承。但我发现这并不优雅,而且将python的灵活性推向了极限。 我真正想做的是有一个类,它只会根据一个条件返回另一个类,然后我就可以用它来继承。有什么提示吗?我想元类(一个我正在努力理解的概念)现在会派上用场。你知道吗
谢谢你给我小费。谢谢您!你知道吗
为什么不让
ChildAsBaseSelector
从Base
继承呢?在您的示例中,super(Testing2, self).__init__()
将解析为object.__init__()
(因此它不会做您期望的事情),但是-正如您提到的-它无论如何都不会被调用,因为它既不在Child1
的__mro__
中,也不在Child2
的__mro__
中。你知道吗无论如何:让您的
Base.__init__()
依赖于子类在调用super().__init__()
之前设置一个属性是不好的设计-如果Base
需要它,那么它应该作为参数传递,或者在Base
本身有一个可用的默认值。你知道吗另外,如果
ChildAsBaseSelector
的唯一存在理由是基于全局/设置/任何东西创建Child1
或Child1
的实例,那么只需使用工厂函数。。。没有“new”关键字真是一件幸事。你知道吗相关问题 更多 >
编程相关推荐