functools.partial希望将位置参数用作关键字参数

41 投票
3 回答
13643 浏览
提问于 2025-04-18 13:23

我在尝试理解 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 个回答

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()

点击这个按钮会出现同样的错误:“得到了多个值用于关键字参数'x'”。

尽管我以为传递的参数是对类的调用,但实际上却是对UI元素本身的一个愚蠢调用(通常是一个False的值),这个值应该放在*_这个通用参数里,然后再是关键字参数x。

1

为了更详细地解释@Martijn-Pieters的回答,这里介绍了如何保持第二个参数的位置特性。在这里,传给g2的参数是作为y来传递的:

def f(x,y) :
    print x+y

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

当我们想要替换f的初始参数时,这种方法是有效的。不过,我不知道如何使用partial来只替换一个三参数函数的第二个参数,同时让第一个和第三个参数按位置传递。 但你可以通过使用一个lambda表达式来实现这个功能。

53

这其实和 functools.partial 没什么关系。你实际上是这样调用你的函数的:

f(1, x=3)

在Python中,首先会处理位置参数,而你的第一个参数是 x。接着,关键字参数会被应用,而你又一次提供了 x

functools.partial() 并没有办法检测到你已经把第一个位置参数当作关键字参数提供了。它不会通过用 y= 关键字参数来替换位置参数来增强你的调用。

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

撰写回答