python - 从动态创建的基列表创建类

标签 python

有什么方法可以从基类的动态列表中创建一个类吗?

def dynamic_class_creator(base, base2):
    class Derived(base, base2):
        pass
    return Derived

class Mixin1(object):
    def greet(self):
        print ("Howdy!")

class Mixin1a(object):
    def insult(self):
        print ("You have a lot to learn.")

class Mixin2(object):
    def insult(self):
        print ("Idiot!")

polite = dynamic_class_creator(Mixin1, Mixin1a)()
polite.greet()
polite.insult()

complex = dynamic_class_creator(Mixin1, Mixin2)()
complex.greet()
complex.insult()

这按预期工作:

Howdy!                    
You have a lot to learn.  
Howdy!                    
Idiot!

但我不知道如何从任意长度的列表中分配这些碱基:

def dynamic_class_creator(*bases):
    class Derived(*bases):
        pass
    return Derived
(...)

给出:

  File "../test2.py", line 4
    class Derived(*bases):  
                  ^         
SyntaxError: invalid syntax 

编辑

一个建议的解决方案:

def dynamic_class_creator(*bases):
    class Derived(bases):
        pass
    return Derived
(...)

给予:

Traceback (most recent call last):
  File "../test2.py", line 20, in <module>
    polite = dynamic_class_creator(Mixin1, Mixin1a)()
  File "../test2.py", line 4, in dynamic_class_creator
    class Derived(bases):
TypeError: Error when calling the metaclass bases
    tuple() takes at most 1 argument (3 given)

最佳答案

您可以使用 type() 构造函数的三参数形式。引用the documentation ,“使用三个参数,返回一个新类型对象。这本质上是 class 语句的动态形式。

# TESTED with Python3
def dynamic_class_creator(*bases):
    return type('Derived', bases, {})

上面的问题是你丢失了class语法。例如,这使得向 Derived 添加方法变得困难。

您可以保留类声明的良好语法,并且仍然使用 metaclass 修改对 type() 的调用。 .

这是一个完整的示例,演示了 metaclass=type() 以及常规基类和混合基类的使用。

# TESTED with Python3
def dynamic_class_creator(*mixins):
    def metaclass(name, bases, members):
        return type(name, bases + mixins, members)

    class Derived(BaseClass, metaclass=metaclass):
        def praise(self):
            print("Good job!")

    return Derived

class BaseClass(object):
    def goodbye(self):
        print("Goodbye!")

class Mixin1(object):
    def greet(self):
        print("Howdy!")

class Mixin1a(object):
    def insult(self):
        print("You have a lot to learn.")

class Mixin2(object):
    def insult(self):
        print("Idiot!")

polite = dynamic_class_creator(Mixin1, Mixin1a)()
polite.greet()
polite.insult()
polite.praise()
polite.goodbye()

complex = dynamic_class_creator(Mixin1, Mixin2)()
complex.greet()
complex.insult()

您可以将任意关键字传递给元类函数。考虑这个例子:

# TESTED with Python3
def mixin_metaclass(name, bases, members, mixins):
    return type(name, bases+mixins, members)

def dynamic_class_creator(*mixins):
    class Derived(metaclass=mixin_metaclass, mixins=mixins):
        pass
    return Derived

最后,请注意,以上所有示例均使用 Python3 进行测试。这是Python2版本:

# TESTED with Python2
def dynamic_class_creator(*mixins):
    def metaclass(name, bases, members):
        return type(name, mixins+bases, members)
    class Derived(object):
        __metaclass__ = metaclass
        def praise(self):
            print("Good job!")
    return Derived

关于python - 从动态创建的基列表创建类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49948455/

相关文章:

python - 是否有关于数据类属性 mypy 错误的解决方法?

python - python程序中的.pyw文件

python - 将 DataFrame 与相似和不相交的列连接起来

python - 如何使用文本文件中的纬度和经度对图像进行地理标记?

python - SciPy稀疏矩阵(COO,CSR): Clear row

python - 在 Python 中可能 - 如果从实例而不是类调用可以检索实例的类方法?

python - 从 Jupyter Notebook 启动 Dash

python - 将 for 循环中的数据保存到单个列表

python - 导入 PyMySQL

python - Telegram Bot 向自己发送消息但不在公共(public)组中