关于python:关于Python3元类的一些问题

Some questions about Python3 metaclass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 est.py",第32行,in打印(Obj.bar)attributeError:"hello"对象没有属性"bar"

为什么元类upperattrmetaclass不起作用?


在python3中,指定元类的方法已从python2以不兼容的方式更改。

自Python3.0以来,指定元类的方法就是使用元类名称,就像它是class语句本身的命名参数一样。

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

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

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

除此之外,正如您所指出的,将__metaclass__属性放入C alss主体中并不是一个错误,但它完全不做任何事情,而是声明具有该名称的属性。

在几个python3.x版本发布之后,这是唯一一个与python 2不兼容的语法更改,并且不能以简单的方式解决,因此代码同时与python2.x和python3.x兼容。

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