元类参数化继承

时间:2010-10-06 21:10:27

标签: c++ python templates metaprogramming metaclass

我已经阅读了一些有关Python元类的教程。我之前从未使用过一个,但我需要一个相对简单的东西,所有的教程似乎都面向更复杂的用例。我基本上想要创建一个具有一些预先指定的主体的模板类,但是将其基类作为参数。由于我从C ++ / D模板中得到了这个想法,这里有一个我想要编写的代码在C ++中的样子:

template<class T>
    class Foo : T {
        void fun() {}
    }

2 个答案:

答案 0 :(得分:9)

尽管可以使用元类完成,但是没有它们就可以做到你想要的,因为Python类本身就是对象。这意味着 - 基本上只需要几乎一对一的C ++代码翻译。除了相对简单之外,它还可以在Python 2和DSP中无需修改地工作。 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()函数中的代码是通常称为class factory的实例或工厂模式的实现。因此,顺便说一句,您可能会发现问题my answerWhat exactly is a Class Factory? {。}}。

编辑:添加了代码,为每个返回的子类创建不同的类名 - 这受到@ aaronasterling的洞察力(在现已删除的评论中)的启发,关于调试时的潜在混淆制造的类总是具有相同的名称。

答案 1 :(得分:0)

这在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