Как использовать декоратор для отправки аргументов функции в python


У меня есть набор функций в python, который получает те же 2 параметра + другие параметры.

def myMethodA (param1, param2, specificParm)
    do code

 def myMethodB (param1, param2, specificParm1 specificParam2)
    do code

Я хотел создать декоратор, который заменит необходимость вызова с первыми 2 параметрами, нажав параметры перед вызовом функции:

@withParams()
def myMethodA (specificParam)
        do code

Но если я опущу параметры, то декоратор не сможет вызвать его, а если я оставлю их, то вызывающий должен также указать их.

В любом случае, чтобы решить эту проблему? Могу ли я что-то сделать с args* , но все равно назвал параметры для specificParam? Кроме того, как я могу ссылаться на param1 и param2 внутри myMethodA

4 3

4 ответа:

Похоже, что вы можете захотеть functools.partial. Он возвращает новую функцию с некоторыми уже заданными параметрами:

import functools

def withParams(func):
    return functools.partial(func,1,2)

@withParams
def myMethodA (param1, param2, specificParam):
    print(param1,param2,specificParam)

@withParams
def myMethodB (param1, param2, specificParam1, specificParam2):
    print(param1,param2,specificParam1, specificParam2)

myMethodA(10)
myMethodB(12,13)
1 2 10
1 2 12 13

Эти два параметра можно добавить при вызове функции в функции-оболочке декоратора как части kwargs. Все оформленные функции автоматически передают эти два параметра в качестве аргументов ключевого слова перед вызовом:

def withParams(func):
    def wrapper(*args, **kwargs):
        kwargs['param1'] = 1
        kwargs['param2'] = 2
        return func(*args, **kwargs)
    return wrapper

@withParams
def add(specificparam, *args, **kwargs):
      print(specificparam)  # 3
      print(args)           # (4,)
      print(kwargs)         # {'param2': 2, 'param1': 1}
      return specificparam + sum(args) + sum(kwargs.values())

print(add(3,4)) # 10

Вы можете отбросить часть args, если все, что вы будете передавать из вызова основной функции, - этоконкретные параметры для каждой функции.

Я бы рекомендовал вам пойти в старую школу и просто переписать имена, используя functools.partial:

# module foo

def func1(common_1, common_2, specific_1):
    pass

def func2(common_1, common_2, specific_2, specific_3):
    pass

Тогда в другом месте (или ниже в файле, если хотите) вы можете сделать следующее:

import functools

import foo

common_args = (1, 'fred')
foo.func1 = functools.partial(foo.func1, *common_args)
foo.func2 = functools.partial(foo.func2, *common_args)

# ...

foo.func1('special')

foo.func2('equally special', 'but different')

Похоже, что вам нужно functools.partial, чтобы предварительно заполнить" постоянные " параметры:

>>> from functools import partial

>>> def myMethodA(param1, param2, specificParm):
        print("myMethodA(", param1, param2, specificParm, ")")

>>>> def myMethodB (param1, param2, specificParm1, specificParam2):
        print("myMethodB(", param1, param2, specificParm1, specificParam2, ")")

>>> preMethodA = partial(myMethodA, "p1", "p2")
>>> preMethodB = partial(myMethodB, "p1", "p2")
>>> preMethodA(34)
myMethodA( p1 p2 34 )
>>> preMethodB(8, 9)
myMethodB( p1 p2 8 9 )