как частично применить произвольный аргумент функции?

Я хочу использовать частичное из functools, чтобы частично применить второй аргумент функции, я знаю, что это легко сделать с лямбдой, а не с частичным, как показано ниже.

>>> def func1(a,b):
...     return a/b
...
>>> func2 = lambda x:func1(x,2)
>>> func2(4)
2

но я строго хочу использовать здесь частичное (ради обучения), поэтому я придумал это.

>>> def swap_binary_args(func):
...     return lambda x,y: func(y,x)
...
>>> func3 = partial(swap_binary_args(func1),2)
>>> func3(4)
2

Можно ли расширить эту стратегию до уровня, на котором я могу частично применять любые аргументы в любом месте, как в следующем псевдокоде

>>>def indexed_partial(func, list_of_index, *args):
...     ###do_something###
...     return partially_applied_function

>>>func5=indexed_partial(func1, [1,4,3,5], 2,4,5,6)

в нашем случае я могу использовать эту функцию следующим образом

>>>func6=indexed_partial(func1, [1], 2)

Возможно ли иметь индексированное частичное, как я хочу? есть ли что-то похожее на это, о чем я не знаю? и, что более важно, является ли идея индексированного частичного в целом хорошей или плохой идеей, почему?

Этот вопрос был помечен как возможный дубликат Можно ли частично применить второй аргумент функции, которая не принимает аргументы ключевого слова? в этом вопросе. ОП спросил, можно ли частично применить второй аргумент, но здесь я спрашиваю, как приготовить функцию, которая может частично применить любой произвольный аргумент


person k4vin    schedule 09.04.2015    source источник
comment
Рассматривали ли вы просто использование именованных аргументов? functools.partial допускает их, и именно так вы справитесь с этим в реальном коде, хотя, возможно, это не подойдет для вашего упражнения.   -  person jwilner    schedule 10.04.2015
comment
Вероятно, вы могли бы что-нибудь приготовить, используя inspect.getargspec и связывание с использованием имен аргументов.   -  person tzaman    schedule 10.04.2015
comment
Частичный @jwilner с аргументом ключевого слова был бы практически эквивалентен тому, чего я пытаюсь достичь, вместо использования индекса я должен использовать ключи. Спасибо :)   -  person k4vin    schedule 10.04.2015
comment
У меня есть (зачаточное) решение, но, как было указано, это невозможно сделать с помощью partial.   -  person haavee    schedule 10.04.2015


Ответы (1)


Я тоже думаю, что то, что вы просите, не может быть сделано (легко?) с functools.partial. Вероятно, лучшее (и наиболее читаемое) решение — использовать partial с ключевыми словами-аргументами. Однако, если вы хотите использовать позиционные аргументы (и, следовательно, индексированные частичные аргументы), вот возможное определение indexed_partial:

def indexed_partial(func, list_of_index, *args):
    def partially_applied_function(*fargs, **fkwargs):
        nargs = len(args) + len(fargs)
        iargs = iter(args)
        ifargs = iter(fargs)
        posargs = ((ifargs, iargs)[i in list_of_index].next() for i in range(nargs))
        return func(*posargs, **fkwargs)
    return partially_applied_function
person davidedb    schedule 11.04.2015