【问题标题】:Shouldn't __metaclass__ force the use of a metaclass in Python?__metaclass__ 不应该强制在 Python 中使用元类吗?
【发布时间】:2010-10-23 12:57:51
【问题描述】:

我一直在尝试学习 Python 中的元类。我明白了主要想法,但我似乎无法激活该机制。据我了解,您可以通过在全局或类级别将 __metaclass__ 设置为 M 来将 M 指定为构建类 K 时的元类。为了测试这一点,我编写了以下程序:

p = print

class M(type):
    def __init__(*args):
        type.__init__(*args)
        print("The rain in Spain")

p(1)
class ClassMeta:
    __metaclass__ = M

p(2)
__metaclass__ = M
class GlobalMeta: pass

p(3)
M('NotMeta2', (), {})

p(4)

但是,当我运行它时,我得到以下输出:

C:\Documents and Settings\Daniel Wong\Desktop>python --version Python 3.0.1 C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 1 2 3 西班牙的雨 4

我不应该在 1 和 2 之后看到“西班牙的雨”吗?这是怎么回事?

【问题讨论】:

  • 双重否定“不...不强制”很难解析。请你解决这个问题好吗?
  • 感谢您的反馈。我认为现在应该更容易理解了。

标签: python oop python-3.x metaclass


【解决方案1】:

在 Python 3(您正在使用)中,元类由类定义中的关键字参数指定:

class ClassMeta(metaclass=M):
  pass

指定 __metaclass__ 类属性或全局变量是 Python 2.x 中的旧语法,不再受支持。另见"What's new in Python 3" 和PEP 2115。

【讨论】:

    【解决方案2】:

    这在 Python 2.6(及更早版本)中可以正常工作,但在 3.0 中元类的指定方式不同:

    class ArgMeta(metaclass=M): ...
    

    【讨论】:

      【解决方案3】:

      元类的语法在 Python 3.0 中有changed。 __metaclass__ 属性在类或模块级别不再特殊。要执行您想要执行的操作,您需要将 metaclass 指定为 class 语句的关键字参数:

      p = print
      
      class M(type):
          def __init__(*args):
              type.__init__(*args)
              print("The rain in Spain")
      
      p(1)
      class ClassMeta(metaclass=M): pass
      

      产量:

      1
      The rain in Spain
      

      如你所愿。

      【讨论】:

        猜你喜欢
        • 2019-02-15
        • 2013-07-03
        • 2016-10-03
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多