[英]How can a subclass be created from a string passed to the superclass in python?
Given a super class with two (or many) sub classes, for the sake of simplicity lets call them Super, Sub1 and Sub2 respectively.给定一个带有两个(或多个)子类的超级 class,为简单起见,我们分别称它们为 Super、Sub1 和 Sub2。 I would like to instantiate Sub1 and Sub2 as follows:我想实例化 Sub1 和 Sub2 如下:
s1 = Super('Sub1')
s2 = Super('Sub2')
ie, passing the name of the sub classes as strings to the constructor of the super class.即,将子类的名称作为字符串传递给超级 class 的构造函数。
Something that came to mind was defining a class variable in Super with the names of the sub classes and with a couple of if statements in the constructor of the Super class the corresponding sub class constructor could be called.想到的事情是在 Super class 的构造函数中定义一个 class 变量,其中包含子类的名称和几个 if 语句,可以调用相应的子 class 构造函数。 I'm not completely sure if that would work, but it just seems messy to me.我不完全确定这是否可行,但对我来说似乎很乱。 Any suggestion on how to tackle this problem with a clean and pythonic approach is welcomed.欢迎任何关于如何用干净和 Pythonic 的方法解决这个问题的建议。
I don't really think this is a good idea.我真的不认为这是一个好主意。 A super class is not meant as a container for a finite list of possible subclasses, that pretty much entirely goes against the point of inheritence.超级 class 并不意味着作为可能子类的有限列表的容器,这几乎完全违背了继承的观点。 If I were you I would instead create a simple factory from which I can construct the objects I want, eg:如果我是你,我会创建一个简单的工厂,从中可以构造我想要的对象,例如:
class Fruit():
...
class Apple(Fruit):
...
class Pear(Fruit):
...
fruits = {
"apple": Apple,
"pear": Pear
}
def make_fruit(name, **kwargs):
return fruits[name](**kwargs)
apple = make_fruit("apple", colour="red")
pear = make_fruit("pear", size="small)
This requires overriding Super.__new__
to make it into a factory function.这需要覆盖Super.__new__
以使其成为工厂 function。
class Super:
def __new__(cls, subclass_name, *args, **kwargs):
for sc in cls.__subclasses__():
if sc.__name__ == subclass_name:
return super().__new__(sc, *args, **kwargs)
raise ValueError("No such subclass")
class Sub1(Super):
pass
class Sub2(Super):
pass
assert type(Super('Sub1')) is Sub1
This requires more work to allow you to define a subclass directly (as Sub1()
will invoke Super.__new__
, since Sub1.__new__
is not defined).这需要更多的工作才能让您直接定义子类(因为Sub1()
将调用Super.__new__
,因为未定义Sub1.__new__
)。
As such, I would prefer a dedicated class method that takes a class name, rather than overriding __new__
.因此,我更喜欢采用 class 名称的专用 class 方法,而不是覆盖__new__
。
class Super:
@classmethod
def subclass_by_name(cls, name, *args, **kwargs):
for sc in cls.__subclasses__():
if sc.__name__ == name:
return sc(*args, **kwargs)
raise ValueError("No such subclass")
assert type(Super.subclass_by_name('Sub1')) is Sub1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.