该 attrs
库确实__init__
为它正在装饰的类生成了一个方法。__new__
但是,元类对和方法有一个明确定义的签名__init__
,其参数由 Python 运行时本身填充,每当class
执行语句时(即连同其主体一起)。
我的意思是 - 它是 Python 运行时在class, name, bases, namespace
对 metaclass 的调用中填充参数 " " __init__
,你不能轻易地改变它,以便class, attr1, attr2
传递它,因为__init__
created byattrs
需要。
简而言之,如果不进一步attrs
查看文档以查看是否可以抑制其覆盖__init__
(以及它创建的一些其他魔术方法),则不能attrs
与元类一起使用。
作为记录,Python 3.7“数据类”允许人们“关闭”__init__
方法的创建,但即便如此,元类也是必须仔细考虑的东西,很难想到用于检测的高级功能仅因为语言语法允许而对元类开箱即用的类。
总而言之,这可能是一个“x,y”问题——我建议不要仅仅因为你认为它的一些特性在那里可以很好地发挥作用,就尝试使用带有元类的 3rd 方包,而是描述它是什么您想在另一个问题中使用自定义元类来实现。
元类方法中的几行代码 __new__
可能会为您提供所需的功能,但不会产生未知的副作用。
特别是,如果您只是想添加my_attribute = attrib()
到使用自定义元类创建的所有类中,则不应尝试在元类中创建它。也许,您只需要一个 Base 超类,根本不需要元类:
from abc import ABC
...
@attrs
class Base(ABC):
my_attribute = attrib()
class MyClass(Base):
pass
同样,我不知道attr
lib,也许它不适用于继承(但我怀疑 - 它应该做得很好),然后你可以使用元类来注入属性并在你的类上应用@attrs
装饰器,但是不要尝试在您的元类本身上这样做:
from attr import attrs, attrib
from abc import ABCMeta
class MetaClass(ABCMeta):
my_attribute = attrib()
def __new__(metacls, name, bases, namespace, **kw):
cls = super().__new__(metacls, name, bases, namespace, **kw)
# if the 'attrs' decorator modifies the type of "cls",
# the original __init__ won't be called automatically.
# since we are inheriting from other superclass, we'd better
# call it manually here, and suppress its automatic execution
# bellow.
super(MetaClass, cls).__init__(cls, name, bases, namespace, **kw)
cls.my_attribute = attrib()
return attrs(cls)
def __init__(cls, name, bases, namespace, **kw):
pass
class MyClass(object, metaclass=MetaClass):
pass