有没有办法从动态基类列表中创建一个类?
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)
答案 0 :(得分:3)
您可以使用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
答案 1 :(得分:0)
为了完整起见,如果你已经在使用另一个元类(就像我一样),这里有一个基于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