关于 Python3 元类的一些问题
Posted
技术标签:
【中文标题】关于 Python3 元类的一些问题【英文标题】:Some questions about Python3 metaclass 【发布时间】: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 不起作用?
【问题讨论】:
Python3 Singleton metaclass method not working的可能重复 为什么这个问题被否决了?它确实有一个完美的代码示例和一个精心设计的问题(如果取决于问题标题)。 【参考方案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)
【讨论】:
以上是关于关于 Python3 元类的一些问题的主要内容,如果未能解决你的问题,请参考以下文章