20

在 Python 中,是否可以在运行时重新定义函数的默认参数?

我在这里定义了一个带有 3 个参数的函数:

def multiplyNumbers(x,y,z):
    return x*y*z

print(multiplyNumbers(x=2,y=3,z=3))

接下来,我尝试(不成功)为 y 设置默认参数值,然后尝试调用不带参数的函数y

multiplyNumbers.y = 2;
print(multiplyNumbers(x=3, z=3))

但是产生了以下错误,因为y没有正确设置默认值:

TypeError: multiplyNumbers() missing 1 required positional argument: 'y'

是否可以在运行时重新定义函数的默认参数,就像我在这里尝试做的那样?

4

4 回答 4

37

只需使用functools.partial

 multiplyNumbers = functools.partial(multiplyNumbers, y = 42)

这里有一个问题:您将无法调用它,因为multiplyNumbers(5, 7, 9);您应该手动说y=7

如果您需要删除默认参数,我看到两种方法:

  1. 将原始功能存储在某处

    oldF = f
    f = functools.partial(f, y = 42)
    //work with changed f
    f = oldF //restore
    
  2. 采用partial.func

    f = f.func //go to previous version.
    
于 2013-07-13T00:11:10.017 回答
17

从技术上讲,可以按照您的要求进行操作……但这不是一个好主意。RiaD 的答案是 Pythonic 的方式来做到这一点。

在 Python 3 中:

>>> def f(x=1, y=2, z=3):
...     print(x, y, z)
>>> f()
1 2 3
>>> f.__defaults__ = (4, 5, 6)
4 5 6

与在文档中很难找到的所有其他内容一样,inspect模块图表是查找函数属性的最佳位置。

Python 2 中的细节略有不同,但思路是一样的。(只需将文档页面左上角的下拉菜单从 3.3 更改为 2.7。)


如果你想知道当 Python 有一个元组时,它如何知道哪些默认值与哪些参数一起使用……它只是从末尾倒数(或*, *args,的第一个——**kwargs之后的任何内容都进入__kwdefaults__dict)。f.__defaults = (4, 5)将默认设置为和y和,默认设置为. 之所以有效,是因为在默认参数之后不能有非默认参数。z45x


在某些情况下这不起作用,但即使那样,您也可以将其不变地复制到具有不同默认值的新函数中:

>>> f2 = types.FunctionType(f.__code__, f.__globals__, f.__name__,
...                         (4, 5, 6), f.__closure__)

在这里,types模块文档并没有真正解释任何内容,但help(types.FunctionType)在交互式解释器中显示了您需要的参数。


您无法处理的唯一情况是内置函数。但是它们通常没有实际的默认值。相反,他们在 C API 中伪造了类似的东西。

于 2013-07-13T00:15:07.447 回答
2

是的,您可以通过修改函数的func.__defaults__元组来完成此操作

该属性是函数每个参数的默认值的元组。

例如,要让pandas.read_csvalways use sep='\t',你可以这样做:

import inspect

import pandas as pd

default_args = inspect.getfullargspec(pd.read_csv).args
default_arg_values = list(pd.read_csv.__defaults__)
default_arg_values[default_args.index("sep")] = '\t'
pd.read_csv.__defaults__ = tuple(default_arg_values)
于 2021-07-02T22:16:31.987 回答
1

使用func_defaults

def myfun(a=3):
    return a

myfun.func_defaults = (4,)
b = myfun()
assert b == 4

在此处查看 func_defaults 的文档

更新:看着 RiaD 的回应,我觉得我的字面意思。我不知道您提出这个问题的背景,但总的来说(并遵循Python 之禅)我相信使用部分应用程序是比重新定义函数的默认参数更好的选择

于 2013-07-13T00:14:25.827 回答