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不起作用?
答案 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)