functools.partial хочет использовать позиционный аргумент в качестве ключевого аргумента
Поэтому я пытаюсь понять partial
:
import functools
def f(x,y) :
print x+y
g0 = functools.partial( f, 3 )
g0(1)
4 # Works as expected
В:
g1 = functools.partial( f, y=3 )
g1(1)
4 # Works as expected
В:
g2 = functools.partial( f, x=3 )
g2(1)
TypeError: f() got multiple values for keyword argument 'x'
TypeError
исчезает, если я использую y
в качестве ключевого аргумента:
В:
g2( y=1 )
4
Что вызывает TypeError
?
2 ответа
Это не имеет ничего общего с functools.partial
, действительно. По сути, вы вызываете свою функцию следующим образом:
f(1, x=3)
Python сначала выполняет позиционные аргументы, а ваш первый аргумент x
, Затем ключевые аргументы применяются, и вы снова предоставили x
,
functools.partial()
не имеет средств обнаружить, что вы уже указали первый позиционный аргумент в качестве ключевого аргумента. Это не увеличит ваш вызов, заменив позиционный аргумент на y=
Ключевой аргумент.
При смешивании позиционных и ключевых аргументов вы должны позаботиться о том, чтобы не использовать один и тот же аргумент дважды.
Чтобы расширить ответ @Martijn-Pieters, это то, как вы можете сохранить позиционную природу второго параметра. Здесь аргумент g2 передается позиционно как y:
def f(x,y) :
print x+y
g2 = functools.partial( f, *[3] )
g2(1)
Это работает, когда мы пытаемся заменить начальный набор аргументов f. Я не знаю как пользоваться partial
заменить, например, только второй аргумент трехпараметрической функции, и разрешить позиционировать первый и третий аргументы. Но вы можете сделать это с лямбда-выражением.
Не ответ, а дополнительный вопрос (поскольку я не могу добавить комментарий без репутации 50), не могли бы вы уточнить или использовать простые термины, поскольку ответы здесь выше моего понимания. У меня аналогичная проблема с использованием кнопки в Maya
import maya.cmds as cmds
from functools import partial
class Myclass(object):
def __init__(self):
pass
def createui(self):
derp = cmds.window()
cmds.formLayout()
cmds.button(label = "w/e", c = partial(self.f, x = 3))
cmds.showWindow(derp)
def f(self, x = 5, y = 3, *_):
print(x+y)
herp = Myclass()
herp.createui()
нажатие на кнопку приведет к той же ошибке "получено несколько значений для аргумента ключевого слова 'x'"
хотя я думал, что в качестве аргументов отправляется вызов класса, какой-то глупый вызов самого элемента пользовательского интерфейса (обычно значение False), который должен быть помещен в аргумент *_ catch all, а затем аргумент ключевого слова x.