是否可以在Python中更改函数的默认参数?

时间:2013-07-13 00:05:17

标签: python function

在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 个答案:

答案 0 :(得分:24)

只需使用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.
    

答案 1 :(得分:7)

从技术上讲,你可以做你所要求的......但这不是一个好主意。 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,{{ 1}} - 之后的任何内容都会转移到**kwargs dict中。 __kwdefaults__会将默认设置为f.__defaults = (4, 5),将y设置为z4,默认设置为5。这是有效的,因为在默认参数之后你不能有非默认参数。


在某些情况下,这不起作用,但即便如此,您仍可以不可避免地将其复制到具有不同默认值的新功能:

x

在这里,types module文档并没有真正解释任何内容,但是交互式解释器中的>>> f2 = types.FunctionType(f.__code__, f.__globals__, f.__name__, ... (4, 5, 6), f.__closure__) 显示了您需要的参数。


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

答案 2 :(得分:0)

中使用func_defaults
def myfun(a=3):
    return a

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

查看func_defaults here

的文档

更新:关注RiaD的反应我觉得我的文字过于粗俗。我不知道你问这个问题的上下文,但总的来说(和Zen of Python之后)我认为使用部分应用程序是比重新定义函数的默认参数更好的选择

答案 3 :(得分:0)

是的,您可以通过修改函数的 func.__defaults__ 元组来实现这一点

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

例如,要使 pandas.read_csv 始终使用 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)