【问题标题】:metaclass `__call__` method not called at instanciation实例化时未调用元类`__call__`方法
【发布时间】:2017-01-13 23:37:37
【问题描述】:

我正在尝试理解元类。

我已经阅读了this answer,并尝试像这样使用自定义__call__

#!/usr/bin/env python3                                                                                               

class MetaTest(type):
    def __call__(cls, *args, **kwargs):
        print("MetaTest.__call__ called.")
        return super().__call__(cls, *args, **kwargs)


class Test:
    __metaclass__ = MetaTest


if __name__ == '__main__':
    Test()

我希望Test.__class__.__call__ 在实例化时被调用,Test.__class__MetaTest 的一个实例,但事实并非如此,因为我在运行此脚本时没有输出。

那么为什么MetaTest.__call__ 不调用Test 实例化

【问题讨论】:

  • 这不是 Python 3.x 中元类使用的正确语法:docs.python.org/3.0/whatsnew/3.0.html#changed-syntax。如果您解决了这个问题,您将看到该方法按预期被调用。
  • @jonrsharpe 确实!我更正了它并调用了__class__.__call__。仍然有一个错误,但这是另一个问题,这个问题已经解决了:)。

标签: python-3.x metaclass


【解决方案1】:

您正在对元类使用 Python 2 语法 - 但您的 shebang 行和标签表明您正在 Python 3 上运行它。

只需更改您的类声明以使用 Python 的 3 方式声明元类:

#!/usr/bin/env python3                                                                                               

class MetaTest(type):
    def __call__(cls, *args, **kwargs):
        print("MetaTest.__call__ called.")
        return super().__call__(cls, *args, **kwargs)


class Test(metaclass=MetaTest):
    pass

if __name__ == '__main__':
    Test()

在类主体上声明 __metaclass__attribute 在 Python 3 中无效,但由于它只是一个属性声明,因此也不会引发错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 2023-04-03
    • 2012-09-02
    • 2015-09-18
    • 1970-01-01
    相关资源
    最近更新 更多