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

And*_*een 11 python function

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

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

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

print(multiplyNumbers(x=2,y=3,z=3))
Run Code Online (Sandbox Code Playgroud)

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

multiplyNumbers.y = 2;
print(multiplyNumbers(x=3, z=3))
Run Code Online (Sandbox Code Playgroud)

但是由于y未正确设置默认值,因此产生了以下错误:

TypeError: multiplyNumbers() missing 1 required positional argument: 'y'
Run Code Online (Sandbox Code Playgroud)

是否有可能在运行时重新定义函数的默认参数,因为我试图在这里做?

Ria*_*iaD 26

只需使用functools.partial

 multiplyNumbers = functools.partial(multiplyNumbers, y = 42)
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 在某处存储原始功能

    oldF = f
    f = functools.partial(f, y = 42)
    //work with changed f
    f = oldF //restore
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用 partial.func

    f = f.func //go to previous version.
    
    Run Code Online (Sandbox Code Playgroud)


aba*_*ert 8

从技术上讲,它可以做你所要求的......但这不是一个好主意.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
Run Code Online (Sandbox Code Playgroud)

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

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


如果你想知道Python的知道它默认与论据去的时候,它只是有一个元组...它只是从终端(或第一向后计数*,*args,**kwargs后-anything进入__kwdefaults__字典代替).f.__defaults = (4, 5)将设置默认为y,并z45,并用默认x.这是有效的,因为在默认参数之后你不能拥有非默认参数.


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

>>> f2 = types.FunctionType(f.__code__, f.__globals__, f.__name__,
...                         (4, 5, 6), f.__closure__)
Run Code Online (Sandbox Code Playgroud)

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


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

  • @AndersonGreen:嗯,有一个明显的缺点,那就是它让你、其他人、linter、IDE、基于反射的工具(如“pickle”)更难理解你的代码。并且您必须完全理解有关 args/params 的规则,以确保您做得正确。事实上,如果不编写可以处理常规函数、奇怪的不可变函数(需要从代码中构造一个新函数)和内置函数(需要包装它们)的代码,就无法使其正常工作。使用“部分”或调用它的新函数)。 (4认同)
  • 您提到在运行时更改函数的默认参数“不是一个好主意”。您是否注意到这种方法的任何缺点?(我还不知道任何)。 (2认同)

gri*_*tis 5

是的,您可以通过修改函数的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)
Run Code Online (Sandbox Code Playgroud)