Python 从动态创建的基列表创建类

Python 从动态创建的基列表创建类,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

有没有办法从基类的动态列表中创建类

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)
回溯(最近一次呼叫最后一次):
文件“./test2.py”,第20行,在
礼貌=动态类创建者(Mixin1,Mixin1a)()
文件“./test2.py”,第4行,在dynamic\u class\u creator中
派生类(基):
TypeError:调用元类基时出错
tuple()最多接受1个参数(给定3个)

您可以使用
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

为了完整性起见,这里有一个基于Rob的解决方案ᵩ'如果您已经在使用另一个元类(就像我一样):

Python 3

def mixin_metaclass(name, bases, members, mixins, super_meta=type):
    return super_meta(name, bases + mixins, members)

def dynamic_class_creator(*mixins):
    class Derived(metaclass=mixin_metaclass, mixins=mixins, super_meta=MyMeta):
        pass
    return Derived
Python 2

def mixin_meta(super_meta, *mixins):
    def _meta(name, bases, members):
        return super_meta(name, mixins + bases, members)
    return _meta

def dynamic_class_creator(*mixins):
    class Derived(object):
        __metaclass__ = mixin_meta(MyMeta, *mixins)
    return Derived

谢谢唯一的问题是,我正在为Python2编写代码(内部限制)。所以我必须做
\uuuuuuuuuuuuuuuuuu=metaclass
。另外,如果我想确保
派生的
对象
的子类,那么它必须是
。。。元组(mixin)+基…
,否则MRO将失败。但这完全有效。谢谢你的评论。我添加了一个Python2示例。
def mixin_meta(super_meta, *mixins):
    def _meta(name, bases, members):
        return super_meta(name, mixins + bases, members)
    return _meta

def dynamic_class_creator(*mixins):
    class Derived(object):
        __metaclass__ = mixin_meta(MyMeta, *mixins)
    return Derived