用元类参数化继承
我看了一些关于Python元类的教程。虽然我之前从来没有用过元类,但我现在需要一个来处理一些相对简单的事情,而所有的教程似乎都在讲一些更复杂的用法。我基本上想创建一个模板类,这个类有一些预先指定的内容,但它的基类是作为参数传入的。因为我这个想法是从C++/D的模板中得到的,所以我想给大家看看我想在C++中写的代码示例:
template<class T>
class Foo : T {
void fun() {}
}
2 个回答
0
在Python中,这个概念没有意义,因为Python没有模板。我的理解是,C++中的参数化模板(我对这个理解得不太清楚,因为我已经很多年没接触过了)就像一个类工厂,可以根据你给它的类创建一个子类,并且可以添加额外的方法或属性。
在Python中,你可以使用一个工厂函数来实现类似的功能,这个函数接收一个类,并在运行时返回一个新的类:
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
10
虽然确实可以通过元类来实现你想要的功能,但其实在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()
函数中的代码是一个常见的例子,通常被称为 类工厂,或者说是 工厂模式 的一种实现。所以,顺便提一下,你可能会觉得我对这个问题的回答 《什么是类工厂?》 也很有帮助。
编辑: 增加了代码,使每个返回的子类都有不同的类名——这个灵感来自于 @aaronasterling 的一个见解(在一条现在已删除的评论中),提到如果制造的类总是有相同的名字,在调试时可能会造成困惑。