【问题标题】:Some questions about Python3 metaclass关于 Python3 元类的一些问题
【发布时间】:2017-05-16 13:35:20
【问题描述】:
class UpperAttrMetaclass(type):

    var = "test"

    def __new__(upperattr_metaclass, future_class_name,
                future_class_parents, future_class_attr):
        print("hello world")
        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        # reuse the type.__new__ method
        # this is basic OOP, nothing magic in there
        return type.__new__(upperattr_metaclass, future_class_name,
                            future_class_parents, uppercase_attr)


class Hello(object):

    __metaclass__ = UpperAttrMetaclass

    bar = "test"

obj = Hello()
print(obj.BAR)  # obj has no attribute named BAR

回溯(最近一次通话最后一次):
文件“E:\python\test.py”,第 32 行,在
打印(obj.BAR)
AttributeError: 'Hello' 对象没有属性 'BAR'

为什么元类 UpperAttrMetaclass 不起作用?

【问题讨论】:

标签: python python-3.x metaclass


【解决方案1】:

在 Python3 中,指定元类的方式与 Python2 发生了不兼容的变化。

从 Python 3.0 开始,指定元类的方法是使用元类名称,就好像它是 class 语句本身的命名参数一样。

因此,在上面的示例中,您应该将 Hello 类声明为:

class Hello(metaclass=UpperAttrMetaclass):
    bar = "test"

查看文档:https://docs.python.org/3.0/whatsnew/3.0.html#changed-syntax

除此之外,正如您所指出的,将 __metaclass__ 属性放在 ac alss 正文中并不是一个错误,但它什么都不做,而是用该名称声明一个属性。

在发布了几个 Python3.x 版本之后,这是唯一与 Python 2 不兼容且无法直接解决的语法更改,因此代码既是 Python 2.x 又是 Python 3 .x 同时兼容。

如果您需要在 Python 2 和 Python 3 上运行相同的代码库,则名为 six 的包会调用 with_metaclass,它使用与两个版本兼容的语法构建动态类库。 (https://pythonhosted.org/six/#syntax-compatibility)

【讨论】:

    猜你喜欢
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2013-07-07
    • 2013-05-10
    • 2012-03-18
    • 2023-03-09
    • 2021-07-01
    相关资源
    最近更新 更多