Просто для иллюстрации, если вы хотите изменить объект attibute (вы говорите, что нет), декоратор будет выглядеть так:
def fallback_args(func):
def inner(obj, **kwargs):
if kwargs:
for key in kwargs:
setattr(obj, key, kwargs[key])
return func(obj, **kwargs)
return inner
class B:
def __init__(self, a=0, b=1):
self.a = a
self.b = b
@fallback_args
def func(self, a=None, b=None):
print("Do something with {} and {}".format(self.a, self.b))
#or
#a = self.a
#b = self.b
#print("Do something with {} and {}".format(a, b))
obj2 = B()
print(obj2.a)
print(obj2.b)
obj2.func()
print()
obj2 = B()
print(obj2.a)
print(obj2.b)
obj2.func(a=300)
print()
print(obj2.a)
print(obj2.b)
Выходы:
0
1
Do something with 0 and 1
0
1
Do something with 300 and 1
300
1
Но не желая менять объект, я не думаю, что имеет смысл просто избегать явных a = self.a or a
подобных линий. Потому что, если вы не перечислите параметры в вызове, как декоратор узнает, какие имена вы упоминаете в теле методов, чтобы использовать их как резервный / загруженный? Можно сказать, что имена являются только теми, которые перечислены в сигнатуре метода. Теперь, это может быть самоанализ, но я думаю, что вижу здесь более запутанную работу, чем это заслуживает. a = self.a or a
выглядит просто и явно. Так что это тоже Pythoni c, хотя вы, вероятно, могли бы написать неявное присваивание, которое вам нужно, с некоторой дополнительной работой.
Для идеи о том, как анализировать аргументы метода, см. Несколько связанный декоратор, который я написал здесь , чтобы заморозить аргументы метода.