Python 请教一个元类使用的问题?

knowway · 2022年02月17日 · 最后由 frankxii 回复于 2022年02月18日 · 1950 次阅读
class LowerAttrMetaClass_4(type):
    def __new__(cls, name, bases, dct):
        attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
        lowercase_attr = dict((name.lower(), value) for name, value in attrs)
        return super(LowerAttrMetaClass_4, cls).__new__(cls, name, bases, lowercase_attr)

class MetaClassTest(object, metaclass=LowerAttrMetaClass_4):
    Say = "hello world"

    def __init__(self, name, age):
        super(MetaClassTest, self).__init__()
        self.name = name
        self.age = age

    def Run(self):
        print("MetaClassTest run method")

tmp_obj = MetaClassTest(name="zzz", age=20)

执行如上代码,总是报如下错误:
DeprecationWarning: class not set defining 'MetaClassTest' as . Was classcell propagated to type.new?
class MetaClassTest(object, metaclass=LowerAttrMetaClass_4):
Traceback (most recent call last):
File "E:/zzz/meta.py", line 286, in
tmp_obj = MetaClassTest(name="zzz", age=20)
TypeError: MetaClassTest() takes no arguments

请教:
(1)为什么会报 DeprecationWarning?
(2)为什么会报 MetaClassTest() takes no arguments,我明明传了参数进去的呀?

共收到 2 条回复 时间 点赞

同楼上,楼主在避免处理魔术方法时把带__的方法都漏掉了,漏掉了__classcell__,所以报 DeprecationWarning,高版本 python 应该会报 RuntimeError,漏掉了__init__,类创建后默认使用了无参初始化方法,所以报 MetaClassTest() takes no arguments

class LowerAttrMetaClass_4(type):
    def __new__(mcs, name, bases, attr):
        attr = {key if key[:2] == "__" else key.lower(): value for key, value in attr.items()}
        return type.__new__(mcs, name, bases, attr)


class MetaClassTest(metaclass=LowerAttrMetaClass_4):
    Say = "hello world"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def Run(self):
        print("MetaClassTest run method")


tmp_obj = MetaClassTest(name="zzz", age=20)
tmp_obj.run()
# >>>
# MetaClassTest run method

class LowerAttrMetaClass_4(type):
def new(cls, name, bases, dct):
lowercase_attr = {}
for name, val in dct.items():
if name.startswith(''):
lowercase_attr[name] = val
else:
lowercase_attr[name.lower()] = val
return super(LowerAttrMetaClass_4, cls).
new__(cls, name, bases, lowercase_attr)

class MetaClassTest(metaclass=LowerAttrMetaClass_4):
Say = "hello world"

def init(self, name, age):
super(MetaClassTest, self).init()
self.name = name
self.age = age

def Run(self):
print("MetaClassTest run method")

tmp_obj = MetaClassTest(name="zzz", age=20)
修改成这样就可以了。你错误的原因是 attrs = ((name, value) for name, value in dct.items() if not name.startswith('')),把类里的其他属性都干掉了,这个开头的类属性都没有了

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册