问题
So I am trying to understand partial
:
import functools
def f(x,y) :
print x+y
g0 = functools.partial( f, 3 )
g0(1)
4 # Works as expected
In:
g1 = functools.partial( f, y=3 )
g1(1)
4 # Works as expected
In:
g2 = functools.partial( f, x=3 )
g2(1)
TypeError: f() got multiple values for keyword argument 'x'
The TypeError
disappears if I use y
as a keyword argument:
In:
g2( y=1 )
4
What causes the TypeError
?
回答1:
This has nothing to do with functools.partial
, really. You are essentially calling your function like this:
f(1, x=3)
Python first fulfils the positional arguments, and your first argument is x
. Then the keyword arguments are applied, and you again supplied x
.
functools.partial()
has no means to detect that you already supplied the first positional argument as a keyword argument instead. It will not augment your call by replacing the positional argument with a y=
keyword argument.
When mixing positional and keyword arguments, you must take care not to use the same argument twice.
回答2:
To expand on @Martijn-Pieters answer, this is how you can preserve the positional nature of the second parameter. Here, the argument to g2 is passed positionally as y:
def f(x,y) :
print x+y
g2 = functools.partial( f, *[3] )
g2(1)
That works when we're trying to replace an initial set of the arguments of f. I don't know how to use partial
to replace e.g. just the second argument of a 3-parameter function, and allow the first and third to be passed positionally.
But you could do that with a lambda expression.
回答3:
Not an answer, a follow up question (since I can't add a comment without 50 reputation), could you please elaborate or use simple terms as the answers here are above my comprehension. I have a similar issue using a button in 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()
clicking on the button will give that same error "got multiple values for keyword argument 'x'"
even though what I thought was being sent as arguments was a call to the class, some stupid call to the UI element itself (usually a value of False) which should be put in the *_ catch all argument, and then keyword argument of x.
来源:https://stackoverflow.com/questions/24755463/functools-partial-wants-to-use-a-positional-argument-as-a-keyword-argument