【问题标题】:python metaclass pass __init__ paramspython元类传递__init__参数
【发布时间】:2018-03-02 09:41:18
【问题描述】:

我正在学习 python 3 中的元类编程,但我遇到了一些问题

class UpperAttrMetaClass(type): # to uppercase all attrs
    def __new__(mcs, class_name, class_parents, class_attr):
        attrs = ((name, value) for name, value in class_attr.items() if not 
            name.startswith('__'))
        uppercase_attrs = dict((name.upper(), value) for name, value in attrs)
        return super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, 
                     class_parents, uppercase_attrs)

class Base(metaclass=UpperAttrMetaClass):
    bar = 12
    def __init__(self, params):
        super(Base, self).__init__()
        self.params = params

t = Base(1)
print(t.BAR)
print(t.params)

此代码可以大写所有属性。

我想给init传递一个参数,但是当我运行这段代码时,我被提示犯了一个错误

TypeError: object() takes no parameters

我该如何解决这个问题?

【问题讨论】:

  • 大写时你把__init__方法全部去掉了。
  • 删除 __init__ 并没有什么不同,无论哪种方式都会出现错误。
  • 为什么不能在这段代码中使用init

标签: python init metaclass


【解决方案1】:

您正在过滤掉__init__ 方法:

attrs = ((name, value) for name, value in class_attr.items() if not 
    name.startswith('__'))

attrs 是所有不以__ 开头的属性。然后将attrs 大写并将它们用于您创建的类,因此__init__ 永远不会用于新类。因为生成的Bar 类没有__init__ 方法,所以使用object.__init__,并且该方法不带参数:

>>> sorted(vars(Base))
['BAR', '__dict__', '__doc__', '__module__', '__weakref__']
>>> Base.__init__
<slot wrapper '__init__' of 'object' objects>

包括所有属性,不过滤,只对没有__的大写:

class UpperAttrMetaClass(type): # to uppercase all attrs
    def __new__(mcs, class_name, class_parents, class_attr):
        attrs = {name if name.startswith('__') else name.upper(): value for name, value in class_attr.items()}
        return super().__new__(mcs, class_name, class_parents, attrs)

我在这里使用了字典理解;注意name if name.startswith('__') else name.upper() 条件表达式,当名称不以__ 开头时,它会生成一个大写的属性名称。

我也使用了super()的0参数形式,毕竟这是Python 3。

现在元类可以正常工作并且Base.__init__ 存在:

>>> sorted(vars(Base))
['BAR', '__dict__', '__doc__', '__init__', '__module__', '__weakref__']
>>> t = Base(1)
>>> t.BAR
12
>>> t.params
1

【讨论】:

  • 谢谢!我意识到我的错误!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多