我正在尝试创建一个元类,它可以从它的基类扩展强制参数。
我有以下基类:
class BaseClass(JSONEncoder):
def __init__(self, field1, field2, ...):
self.field1 = field1
self.field2 = field2
...
总共有大约10个参数。
然后,我创建一个dict
对象,它包含满足BaseClass的所有参数和值,并使用以下命令创建我的元类:
# getMandatoryFields returns {'field1': 'value1', 'field2': 'value2, ...}
mandatory_fields = self.getMandatoryFields(my_data)
ChildClass = type('ChildClass', (BaseClass,), mandatory_fields)
然而,在我尝试扩展dict之前,我得到了一个错误,即BaseClass中所有必需的位置参数都丢失了:
TypeError: __init__() missing 10 required positional arguments: 'field1', 'field2',...
我认为这与dict解包有关,但我似乎无法找到这些值。我假设这是可能的,因为我可以将一个类传递给type
构造函数以进行继承,但我似乎找不到答案。
1条答案
按热度按时间nuypyhwy1#
你的代码所做的是创建一个新的类,它拥有你想要的默认值作为类属性--好吧。但它并不涉及
__init__
函数本身:它仍然需要10个参数-它不知道从类属性中提取默认值。你必须意识到,虽然在类的
__init__
方法中接收参数并设置具有相同名称的示例属性是常见的做法,但这只是在纯代码中完成的:语言本身中的nothing()将类(或示例)属性名与__init__
中的参数名联系起来。()好吧,在核心语言中“什么都没有”-尽管这是一种常见的做法,在游戏的后期,Python抛出了dataclasses模块,它确实做到了这一点:假设您需要一个
__init__
,它的属性与类中声明的属性镜像并自动生成。如果你的基类上的
__init__
方法只是这样做,并且不调用其他代码,不对接收到的参数进行操作,什么都不做,你可以在你的问题中使用数据类-通过调用type
生成的动态类将覆盖默认值:注意到你没有在基类中编写
__init__
:数据类将为您生成一个。如果你在__init__
中有一些基本代码要执行,数据类支持__post_init__
方法,该方法只接收self
作为参数,并在设置示例属性后调用:把你需要的代码放在里面。(注意,这种方法可能与更高级的数据类使用不兼容,例如使用
dataclasses.field
在基本体中创建更智能的默认值)如果由于某种原因你不能使用数据类(基类不在你的控制之下,或者它对接收到的参数执行一些计算),那么你需要在你创建的类中创建一个
__init__
的修饰版本。我们的想法是构建一个装饰器,它将检查
__init__
签名中的参数名,并尝试在调用原始__init__
之前从类属性中提取这些参数名(如果它们没有作为**kwargs
传入)。不过,我认为数据类只适用于您的情况。