Частичное использование functools с несколькими аргументами - PullRequest
0 голосов
/ 29 марта 2020

Предположим, у меня есть функция

def func(u,v,w,x, alpha = 4, beta = 5):
    print('u ',u)
    print('v ',v)
    print('x ',w)
    print('u ',x)
    print('** kwarqs: alpha ',alpha)
    print('** kwarqs: beta ',beta)
    return u*4 + v*3 + w*2 + x

Теперь я хочу сделать ее частичной с помощью functools.partial. Я устанавливаю переменную u,v,w в константу и создаю функцию $$ part = f (x) | _ {u, v, w = \ text {const}} $$

u = 2
v = 4
w = 5

part = partial(func,u,v,w, alpha = 'Hello 1', beta = 'Hello 2')
print(part(4))

Результат is

u  2
v  4
w  5
x  4   # This is the remaining free variable
** kwarqs: alpha  Hello 1
** kwarqs: beta  Hello 2
34

Как я могу создавать функции

f(u) #or f(v),f(w)
f(v,x) #or all other variable combinations
f(v,alpha) # a combination of args and kwargs

?

С уважением


Обходные пути также приветствуются.

Ответы [ 2 ]

0 голосов
/ 29 марта 2020

Интересная проблема. Вы можете go и превратить свою функцию в функцию только kwarg:

from functools import wraps, partial

def kwarged(func):
    @wraps(func)
    def wrapper(**kwargs):
        return func(**kwargs)
    return wrapper

, которую затем можно использовать для построения любой частичной версии:

>>> func = kwarged(func)

>>> f_u = partial(func, v=5, w=2, x=4)
>>> f_u(u=7)
u  7
v  5
w  2
x  4
** kwarqs: alpha  4
** kwarqs: beta  5
51

>>> f_vx = partial(func, u=5, w=2) 
>>> f_vx(v=3, x=6)
u  5
v  3
w  2
x  6
** kwarqs: alpha  4
** kwarqs: beta  5
39
>>> f_vx(v=3, x=6, alpha=9)
u  5
v  3
w  2
x  6
** kwarqs: alpha  9
** kwarqs: beta  5
39

И даже при том, что все аргументы являются kwargs со значениями по умолчанию, вам все равно придется передать все исходные позиционные аргументы, не установленные частично:

>>> f_vx(v=3, alpha=9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in wrapper
TypeError: func() missing 1 required positional argument: 'x'
0 голосов
/ 29 марта 2020

Могу ли я порекомендовать использовать lambda для вашего случая.

f1 = lambda u : func(u,v,w,x, alpha = 4, beta = 5) 
f2 = lambda v, x: func(u,v,w,x, alpha = 4, beta = 5) 
f3 = lambda v, alpha: func(u,v,w,x, alpha = alpha, beta = 5)  

Использование такое же, как вы хотели:

f1(u) #or f(v),f(w)
f2(v,x) #or all other variable combinations
f3(v,alpha) # a combination of args and kwargs
...