Aynı amaç için bir şeye ihtiyacım vardı, ancak mevcut cevapların hiçbiri test ettiğim tüm vakaları kapsamıyordu. Nadia'nın cevabı aradığıma en yakın olanıydı, bu yüzden onun kodunu temel alarak başladım.
Aşağıdaki dekoratör, tüm geçerli bağımsız değişken kombinasyonlarıyla çalışır:
Positional __init__(self, a, b )
Keyword __init__(self, a=None, b=None )
Positional + Keyword __init__(self, a, b, c=None, d=None)
Variable Positional __init__(self, *a )
Variable Positional + Keyword __init__(self, *a, b=None )
Variable Positional + Variable Keyword __init__(self, *a, **kwargs )
Positional + Variable Positional + Keyword __init__(self, a, *b, c=None )
Positional + Variable Positional + Variable Keyword __init__(self, a, *b, **kwargs )
Keyword Only __init__(self, *, a=None )
Positional + Keyword Only __init__(self, a, *, b=None )
Ayrıca , sınıf örneklerine atanmayacak -özel değişkenlere _
izin vermek için standart -önek kuralını uygular __init__
.
from functools import wraps
import inspect
def auto_assign_arguments(function):
@wraps(function)
def wrapped(self, *args, **kwargs):
_assign_args(self, list(args), kwargs, function)
function(self, *args, **kwargs)
return wrapped
def _assign_args(instance, args, kwargs, function):
def set_attribute(instance, parameter, default_arg):
if not(parameter.startswith("_")):
setattr(instance, parameter, default_arg)
def assign_keyword_defaults(parameters, defaults):
for parameter, default_arg in zip(reversed(parameters), reversed(defaults)):
set_attribute(instance, parameter, default_arg)
def assign_positional_args(parameters, args):
for parameter, arg in zip(parameters, args.copy()):
set_attribute(instance, parameter, arg)
args.remove(arg)
def assign_keyword_args(kwargs):
for parameter, arg in kwargs.items():
set_attribute(instance, parameter, arg)
def assign_keyword_only_defaults(defaults):
return assign_keyword_args(defaults)
def assign_variable_args(parameter, args):
set_attribute(instance, parameter, args)
POSITIONAL_PARAMS, VARIABLE_PARAM, _, KEYWORD_DEFAULTS, _, KEYWORD_ONLY_DEFAULTS, _ = inspect.getfullargspec(function)
POSITIONAL_PARAMS = POSITIONAL_PARAMS[1:]
if(KEYWORD_DEFAULTS ): assign_keyword_defaults (parameters=POSITIONAL_PARAMS, defaults=KEYWORD_DEFAULTS)
if(KEYWORD_ONLY_DEFAULTS): assign_keyword_only_defaults(defaults=KEYWORD_ONLY_DEFAULTS )
if(args ): assign_positional_args (parameters=POSITIONAL_PARAMS, args=args )
if(kwargs ): assign_keyword_args (kwargs=kwargs )
if(VARIABLE_PARAM ): assign_variable_args (parameter=VARIABLE_PARAM, args=args )
Not:
Testleri dahil ettim, ancak kısa olması için son satıra ( 58 ) ayırdım. Tüm olası kullanım durumlarını detaylandıran testleri, find/replace
tüm $
karakterleri yeni satır ile genişletebilirsiniz .
autoassign
tarifi tartışmasına ve alternatif birautoargs
uygulamaya bakın: Python'da otomatik öznitelik ataması yapmanın en iyi yolu nedir ve bu iyi bir fikir mi? - Stack Overflow