functools.partial可以用于绑定任意位置参数吗?

时间:2013-03-26 18:25:06

标签: python

假设您要以任意顺序定义部分设置位置参数,即您希望将部分应用于 str.split 修复第2和第3个参数。期望的结果与:

相同
lambda s: str.rsplit(s, SEP, 1) # SEP given.

(我使用str.rsplit(s...代替s.rsplit(...来明确这一点。)

使用 functools.partial 的一些近似值是:

partial(str.rsplit, sep=SEP, maxsplit=1) # SEP given

str.rsplit 不使用关键字参数,只使用位置。

如何修复部分参数? 是唯一的选择lamda和包装器吗?

如果你想定义内联函数,

包装器是丑陋的,比如为一个函数的参数定义它。 Lambda 在这里是 defacto partial 是另一种选择,但在这种情况下似乎缺乏。

2 个答案:

答案 0 :(得分:4)

对于str.rsplit,您确实想要使用operator.methodcaller()

>>> from operator import methodcaller
>>> SEP = ' '
>>> s = methodcaller('rsplit', SEP, 1)
>>> s('Test one two')
['Test one', 'two']

答案 1 :(得分:4)

partial无法做到这一点。这是因为split使用了来自C API的PyArg_ParseTuple函数,该函数不提供关键字参数。从python的角度来看,如果方法被定义为:

def split(self, *args):
    if len(args) > 2:
        raise TypeError(...)
    sep = args[0] if args else None
    maxsplit = args[1] if len(args) > 1 else -1
    ...

Partial只能按顺序分配位置参数。 documentation中提到了这一点,他们指出partial“大致相当于”:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

注意return func(*(args + fargs), **newkeywords),它清楚地表明您传递给partial的参数被添加到其他函数参数之前。

结论是lambdapartial更强大。

另外,在python3.3中,您可以将maxsplit指定为关键字参数:

>>> 'some string with spaces'.split(maxsplit=2)
['some', 'string', 'with spaces']

对于具有相同问题的许多其他方法/功能也是如此。