关于Python3元类的一些问题

时间:2017-01-02 12:32:03

标签: python python-3.x metaclass

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:'你好'对象没有属性' BAR'

为什么元类UpperAttrMetaclass不起作用?

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

除此之外,正如您所指出的那样,将__metaclass__属性放入ac alss body并不是错误,但它根本不会 ,而是声明具有该名称的属性

在几个版本的Python3.x版本之后,这是唯一与Python 2不兼容的语法更改,无法以简单的方式解决,因此代码是Python 2.x和Python 3 .x同时兼容。

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