用于参数化继承的元类

发布于 2024-09-26 13:31:33 字数 249 浏览 8 评论 0原文

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

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

I've read some tutorials on Python metaclasses. I've never used one before, but I need one for something relatively simple and all the tutorials seem geared towards much more complex use cases. I basically want to create a template class that has some pre-specified body, but takes its base class as a parameter. Since I got the idea from C++/D templates, here's an example of what the code I want to write would look like in C++:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小镇女孩 2024-10-03 13:31:33

虽然这当然可以使用元类来完成,但您可以在没有元类的情况下做您想做的事情,因为在 Python 中,类本身就是对象。令人惊讶的是,这意味着本质上只需要对 C++ 代码进行几乎一对一的翻译。除了因此相对简单之外,它也无需修改即可在 Python 2 和 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 的见解(在现已删除的评论中)关于调试时如果制造的类始终具有相同名称的潜在混乱。

Although it certainly can be done with metaclasses, you can do what you want without them because in Python classes are themselves objects. The means that—surprisingly—essentially nothing more than an almost one-to-one translation of the C++ code is required. Besides being relatively uncomplicated because of this, it'll also work without modification in both 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()

Output:

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()

The code in the (unimaginatively-named) template() function is an example of what is commonly called a class factory or an implementation of the Factory pattern. So, incidentally, you might find my answer to the question What exactly is a Class Factory? informative.

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.

掩饰不了的爱 2024-10-03 13:31:33

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文