简体   繁体   English

如何从传递给 python 中的超类的字符串创建子类?

[英]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.

相关问题 python子类无法从超类导入超类 - python subclass can't import superclass from superclass Python 和类 - 我可以在超类中使用将在子类中创建的方法吗? - Python & Classes - Can I use a method in a superclass that is going to be created in a subclass? 可以将python子类存储在其超类的单独模块中 - Can a python subclass be store in a seperate module from its superclass Python 中的子类可以访问其超类的属性吗? - Can a subclass access attributes from its superclass in Python? python 超类可以从其子类调用 function 吗? - python Superclass can call a function from its subclass? 如何从超类调用Subclass对象,还有更好的方法吗? (Python 3) - How can I call a Subclass object from a Superclass and is there a better way to do this? (Python 3) 如何覆盖 SUBclass 中依次覆盖 SUPERclass 的函数(Python)? - How can I override the function in SUBclass that overrides the SUPERclass in turn (Python)? Python 2.7在超类中具有关键字参数的功能:如何从子类访问? - Python 2.7 function with keyword arguments in superclass: how to access from subclass? Python:如何从超类创建子类? - Python: How do I make a subclass from a superclass? 如何键入提示从 Python 中的超类列表返回子类的实例 - How to type hint a return an instance of a subclass from a list of superclass in Python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM