functools.partial想要将一个位置参数用作关键字参数

41

所以我正在尝试理解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'

如果我使用 y 作为关键字参数,TypeError 将消失:

代码段:

g2( y=1 )

4

什么会导致 TypeError 错误?
3个回答

53

这与 functools.partial 没有任何关系,实际上你只是这样调用你的函数:

f(1, x=3)

Python首先满足位置参数,您的第一个参数是x。然后应用关键字参数,并且您再次提供了x

functools.partial()无法检测到您已将第一个位置参数作为关键字参数提供。它不会通过使用y=关键字参数替换位置参数来增强您的调用。

在混合使用位置和关键字参数时,必须注意不要重复使用同一参数。


1
有没有一种方法可以以任意方式填充默认参数,然后使函数只保留一个参数,在args/kwargs链中可以尽可能地深? - chiffa
@chiffa:我不确定你的意思。除非函数有*args**kwargs参数,否则你不能仅仅传递任意参数给一个函数。如果一个函数有关键字参数(name=some_default),那么你不必为它们提供任何东西,如果你省略它们,它们已经有了默认值。 - Martijn Pieters
我意识到这是我的问题。我试图绘制一个带有多个参数的函数图,其中一组参数总是以相同的方式变化,而其他一些参数需要更改以绘制对比图,并简化编写这些图表,我尝试生成一个部分函数,它会自动提供那些不改变的参数。这起作用了,但我需要将参数提供给部分函数,如 my_partial_function(param_name=param) - chiffa

1
为了进一步解释@Martijn-Pieters的答案,以下是如何保留第二个参数的位置性质。在这里,g2的参数被传递为y的位置参数:
def f(x,y) :
    print x+y

g2 = functools.partial( f, *[3] )
g2(1)

这适用于替换f的初始参数集时。我不知道如何使用partial仅替换三参数函数的第二个参数,并允许第一个和第三个以位置方式传递。但是,您可以使用lambda表达式来实现。

0

这不是一个答案,而是一个跟进问题(因为我没有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()

点击按钮会出现相同的错误“got multiple values for keyword argument 'x'”,尽管我认为被发送作为参数的内容是对类的调用,实际上是对UI元素本身的愚蠢调用(通常是False值),应该将其放在*_ catch all参数中,然后是x的关键字参数。

2
如果有帮助的话,您应该打开一个新问题并引用这个问题。这有助于保持事情的整洁和可搜索性。 - Catsy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接