我有一个派生类,__init__
方法只调用super().__init(...)
。但是,超级类的参数列表非常长,这使得一个主要是锅炉板的列表很长:
def __init__(self, dataset, updater=None,
start_date=None,
end_date=None,
fill_missing_only=False,
total_sync: bool = False,
force: bool = False,
allow_missing: bool = False,
backfill=''):
super().__init__(self, dataset, updater,start_date, end_date,fill_missing_only,total_sync,force,allow_missing,backfill)
有没有办法删除它并让子类自动调用基本的init()方法?
答案 0 :(得分:3)
我看到两种可能性:
只是省略了子类中的__init__
方法 - 如果你实际上没有覆盖任何东西。
使用
def __init__(*args, **kwargs):
super().__init__(*args, **kwargs)
除了super().__init__
调用之外还做其他一些事情,但不需要所有参数。
答案 1 :(得分:0)
最简单的方法是完全删除孩子的__init__
。将自动调用父级__init__
,并保留注释。请记住,__init__
只是一种方法,因此就像其他方法一样受制于MRO。此方法仅在子__init__
具有与父项完全相同的签名且不需要任何其他功能时才有效。
如果孩子对__init__
具有相同的签名但不需要其他参数,则可以执行以下操作:
def __init__(*args, **kwargs):
# Do stuff here
super().__init__(*args, *kwargs)
# Do stuff here
这里唯一的问题是在这种情况下不保留父母的注释。如果这对您很重要,您可以直接从父级复制__annotations__
属性,因为函数__annotations__
是一个可变且可分配的字典。确保一致完成的最简单方法可能是装饰器:
def copy_annotations(parent_fn):
def annotator(fn):
fn.__annotations__ = parent_fn.__annontations__
return fn
return annotator
...
@copy_annotations(Parent.__init__)
def __init__(self, *args, **kwargs):
...
super().__init__(*args, **kwargs)
如果孩子与父母没有相同的签名(即,它有其他参数),请尝试先放置这些参数。例如,如果这是父级的__init__
签名
def __init__(self, dataset, updater=None,
start_date=None,
end_date=None,
fill_missing_only=False,
total_sync: bool = False,
force: bool = False,
allow_missing: bool = False,
backfill=''):
您可以按如下方式定义孩子:
def __init__(self, child_param1: int = 0,
child_param2: bool = False,
*args, **kwargs):
# Do stuff with child_param1, child_param2
super().__init__(*args, **kwargs)
如果您需要混合顺序(以便子参数不是全部第一个),您可能必须进行一些元组数学以获得所需的结果。例如,如果dataset
必须是孩子__init__
的第一个参数,则可以这样定义:
def __init__(self, dataset,
child_param1: int = 0,
child_param2: bool = False,
*args, **kwargs):
# Do stuff with child_param1, child_param2
super().__init__(*((dataset,) + args), **kwargs)
这是有效的,因为args
始终是tuple
,因此您可以在解包之前将(dataset,)
添加到其中。如果根据子参数计算父级的一些参数,这种技术也会起作用。
如果您仍想保留注释,那么装饰器将会稍微复杂一些。您不想复制父项的__annotations__
属性,而是希望将其与现有字典合并:
def copy_annotations(parent_fn):
def annotator(fn):
original = fn.__annotations__
fn.__annotations__ = parent_fn.__annontations__
fn.__annotations__.update(original)
return fn
return annotator