我已经阅读了一些关于 Python 元类的教程。我以前从未使用过,但我需要一个相对简单的东西,而且所有教程似乎都针对更复杂的用例。我基本上想创建一个模板类,它具有一些预先指定的主体,但将其基类作为参数。因为我是从 C++/D 模板中得到这个想法的,所以这里有一个我想编写的代码在 C++ 中的示例:
template<class T>
class Foo : T {
void fun() {}
}
我已经阅读了一些关于 Python 元类的教程。我以前从未使用过,但我需要一个相对简单的东西,而且所有教程似乎都针对更复杂的用例。我基本上想创建一个模板类,它具有一些预先指定的主体,但将其基类作为参数。因为我是从 C++/D 模板中得到这个想法的,所以这里有一个我想编写的代码在 C++ 中的示例:
template<class T>
class Foo : T {
void fun() {}
}
虽然它当然可以用元类来完成,但你可以在没有它们的情况下做你想做的事,因为在 Python 中,类本身就是对象。这意味着——令人惊讶的是——基本上只需要几乎一对一的 C++ 代码翻译。除了因此相对简单之外,它还可以在 Python 2 和 3 中无需修改即可工作。
def template(class_T):
"""Factory function to create subclasses of class_T."""
class Foo(class_T):
def fun(self):
print('%s.fun()' % self.__class__.__name__)
Foo.__name__ += '_' + class_T.__name__ # rename the subclass to reflect its heritage
return Foo
class Base1:
def bar(self):
print('Base1.bar()')
class Base2:
def bar(self):
print('Base2.bar()')
Foo_Base1 = template(Base1)
print('Foo_Base1 base classes: {}'.format(Foo_Base1.__bases__))
Foo_Base2 = template(Base2)
print('Foo_Base2 base classes: {}'.format(Foo_Base2.__bases__))
subclass1 = Foo_Base1()
subclass1.fun()
subclass1.bar()
subclass2 = Foo_Base2()
subclass2.fun()
subclass2.bar()
输出:
Foo_Base1 base classes: (<class __main__.Base1 at 0x00A79C38>,)
Foo_Base2 base classes: (<class __main__.Base2 at 0x00A79DC0>,)
Foo_Base1.fun()
Base1.bar()
Foo_Base2.fun()
Base2.bar()
(难以想象的命名)template()
函数中的代码是通常称为类工厂或工厂模式实现的示例。所以,顺便说一句,你可能会找到我对什么是类工厂这个问题的回答?内容丰富。
Edit: Added code to create different class names for each subclass returned—which was inspired by @aaronasterling's insight (in a now deleted comment) about potential confusion when debugging if the class manufactured always has the same name.
This is meaningless in Python, since it does not have templates. My understanding of parameterized templates in C++ (which is rather vague, since it is many years since I have looked at them), is that it acts like a class factory, and can create a subclass of whatever class you give it that has additional methods or attributes added.
In Python you can do this with a factory function that takes a class and returns a new class at runtime:
In [1]: def subclassFactory(cls):
...: class Foo(cls):
...: def fun(self):
...: return "this is fun"
...: return Foo
...:
In [2]: class A(object):
...: pass
...:
In [5]: C = subclassFactory(A)
In [6]: C
Out[6]: <class '__main__.Foo'>
In [7]: c = C()
In [9]: c.fun()
Out[9]: 'this is fun'
In [10]: isinstance(c, A)
Out[10]: True