我有一个函数 foo
调用 math.isclose
:
import math
def foo(..., rtol=None, atol=None):
...
if math.isclose(x, y, rel_tol=rtol, abs_tol=atol):
...
...
以上在 math.isclose
中失败了如果我不将 rtol
和 atol
传递给 foo
:
TypeError: must be real number, not NoneType
我不想将系统默认参数值放在我的代码中(什么 如果他们改变了?)
这是我到目前为止的想法:
import math
def foo(..., rtol=None, atol=None):
...
tols = {}
if rtol is not None:
tols["rel_tol"] = rtol
if atol is not None:
tols["abs_tol"] = atol
if math.isclose(x, y, **tols):
...
...
这看起来又长又傻,每次调用时都会分配一个 dict
foo
(递归调用自身,所以这很重要)。
那么,告诉math.isclose
的最好方法是什么?使用默认值
公差?
PS。有几个相关的问题。请注意,我确实不想知道 math.isclose
的实际默认参数- 我只想告诉它使用默认值。
最佳答案
一种方法是使用可变参数解包:
def foo(..., **kwargs):
...
if math.isclose(x, y, **kwargs):
...
这将允许您指定 atol
和 rtol
作为主函数 foo
的关键字参数,然后它将原样传递给math.isclose
.
但是,我还要说,传递给 kwargs
的参数以某种方式修改函数的行为,而不是仅仅传递给被调用的子函数,这是惯用的。因此,我建议改为命名一个参数,以便清楚地将其解包并原封不动地传递给子函数:
def foo(..., isclose_kwargs={}):
...
if math.isclose(x, y, **isclose_kwargs):
...
您可以在 matplotlib
中看到等效模式(例如:plt.subplots
- subplot_kw
和 gridspec_kw
,所有其他关键字参数都被传递Figure
构造函数作为 **fig_kw
)和 seaborn
(例如:FacetGrid
- subplot_kws
,gridspec_kws
)。
当有 多个 子函数您可能想要传递关键字参数但保留默认行为时,这一点尤其明显:
def foo(..., f1_kwargs={}, f2_kwargs={}, f3_kwargs={}):
...
f1(**f1_kwargs)
...
f2(**f2_kwargs)
...
f3(**f3_kwargs)
...
警告:
请注意 default arguments are only instantiated once ,因此您不应修改函数中的空 dicts
。如果需要,您应该使用 None
作为默认参数,并在每次运行函数时实例化一个新的空 dict
:
def foo(..., isclose_kwargs=None):
if isclose_kwargs is None:
isclose_kwargs = {}
...
if math.isclose(x, y, **isclose_kwargs):
...
我的偏好是在您知道自己在做什么的情况下避免这种情况,因为它更简短,而且通常我不喜欢重新绑定(bind)变量。但是,它绝对是一个有效的成语,而且它可以更安全。
关于python - 如何告诉函数使用默认参数值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55497837/