假设我有两个不同的类
实现class ParentA:
def initialize(self):
pass
def some_event(self):
pass
def order(self, value):
# handle order in some way for Parent A
class ParentB:
def initialize(self):
pass
def some_event(self):
pass
def order(self, value):
# handle order in another for Parent B
如何动态地让某些第3类继承ParentA
或ParentB
基于这样的内容?
class MyCode:
def initialize(self):
self.initial_value = 1
def some_event(self):
# handle event
order(self.initial_value)
# let MyCode inherit from ParentA and run
run(my_code, ParentA)
答案 0 :(得分:47)
只需将类对象存储在变量中(在下面的示例中,它名为base
),并使用class
语句的基类规范中的变量。
def get_my_code(base):
class MyCode(base):
def initialize(self):
...
return MyCode
my_code = get_my_code(ParentA)
答案 1 :(得分:5)
此外,您可以使用type
内置。作为可调用的,它需要参数:name, bases, dct
(最简单的形式)。
def initialize(self):
self.initial_value = 1
def some_event(self):
# handle event
order(self.initial_value)
subclass_body_dict = {
"initialize": initialize,
"some_event": some_event
}
base_class = ParentA # or ParentB, as you wish
MyCode = type("MyCode", (base_class, ), subclass_body_dict)
这比snx2解决方案更明确,但仍然 - 我更喜欢他的方式。
PS。当然,您不必存储base_class,也不必存储subclass_body_dict,您可以在type()
调用中构建这些值,如:
MyCode = type("MyCode", (ParentA, ), {
"initialize": initialize,
"some_event": some_event
})
答案 2 :(得分:1)
就像一个快速复制和粘贴准备好的片段一样,我添加了来自 shx2's answer 的注释来创建它(使用 created_classes
dict 属性记忆,以便由连续创建的类相同类的相同调用将提供相同的类):
class ParentA:
val = "ParentA"
class ParentB:
val = "ParentB"
class DynamicClassCreator():
def __init__(self):
self.created_classes = {}
def __call__(self, *bases):
rep = ",".join([i.__name__ for i in bases])
if rep in self.created_classes:
return self.created_classes[rep]
class MyCode(*bases):
pass
self.created_classes[rep] = MyCode
return MyCode
creator = DynamicClassCreator()
instance1 = creator(ParentA, ParentB)()
print(instance1.val) #prints "ParentA"
instance2 = creator(ParentB, ParentA)()
print(instance2.val) #prints "ParentB"
如果你想变得有趣,你甚至可以让 DynamicClassCreator 成为单例:https://stackoverflow.com/a/7346105/5122790
答案 3 :(得分:0)
作为 Chris's answer 实现 shx2's answer 备忘建议的替代方法,我更喜欢使用 memoize decorator(最终结果仍然是一个类,但我更清楚的是function 是接口),并且还使用 setdefault
来简化添加到 memo dict 中,并且不将名称转换为字符串而是使用元组 bases
本身作为键,将代码简化为:< /p>
class Memoize:
def __init__(self, f):
self.f = f
self.memo = {}
def __call__(self, *args):
return self.memo.setdefault(args, self.f(*args))
class ParentA:
def initialize(self):
pass
class ParentB:
def initialize(self):
pass
@Memoize
def get_my_code(base):
class MyCode(base):
def initialize(self):
pass
return MyCode
a1 = get_my_code(ParentA)
a2 = get_my_code(ParentA)
b1 = get_my_code(ParentB)
print(a1 is a2) # True
print(a1 is b1) # False
(不是一个很好的例子,因为提供的代码除了覆盖父类的 initialize
方法之外实际上没有做任何事情......)