我有一个函数foo调用math.isclose:

import math
def foo(..., rtol=None, atol=None):
    ...
    if math.isclose(x, y, rel_tol=rtol, abs_tol=atol):
        ...
    ...

如果我没有通过rtolatolfoo,以上内容将在math.isclose分失败:

TypeError: must be real number, not NoneType

我不想在代码中使用系统默认参数值(什么

以下是我到目前为止的 idea :

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):
        ...
    ...

这看起来又长又傻,每次调用

那么,告诉math.isclose使用默认值的最佳方式是什么

还有几个相关的问题.请注意,我不想知道math.isclose的实际默认参数——我只想让它告诉它使用默认值,不管它们是什么.

推荐答案

一种方法是将可变参数解包:

def foo(..., **kwargs):
    ...
    if math.isclose(x, y, **kwargs):
        ...

这将允许您将atolrtol指定为主函数foo的关键字参数,然后它将原封不动地传递给math.isclose.

然而,我还要说,传递给kwargs的参数会以某种方式修改函数的行为,而不仅仅是传递给被调用的子函数,这是惯用的做法.因此,我建议取而代之的是,命名一个参数,这样就可以清楚地看到它将被解包并原封不动地传递给一个子函数:

def foo(..., isclose_kwargs={}):
    ...
    if math.isclose(x, y, **isclose_kwargs):
        ...

您可以在matplotlib(示例:plt.subplots-subplot_kwgridspec_kw,所有其他关键字参数都作为**fig_kw传递给Figure构造函数)和seaborn(示例:FacetGrid-subplot_kwsgridspec_kws)中看到一个等效模式.

当有mutiple个子函数需要传递关键字参数时,这一点尤其明显,否则将保留默认行为:

def foo(..., f1_kwargs={}, f2_kwargs={}, f3_kwargs={}):
    ...
    f1(**f1_kwargs)
    ...
    f2(**f2_kwargs)
    ...
    f3(**f3_kwargs)
    ...

Caveat:

注意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):
        ...

我倾向于在你知道自己在做什么的情况下避免这种情况,因为它更简短,一般来说,我不喜欢重新绑定变量.然而,这绝对是一个有效的习语,而且可能更安全.

Python-3.x相关问答推荐

使用魔方无法从图像中识别单个字符

是否有必要使用Threads()中的args显式地将共享变量传递给Python中的线程函数或直接访问它?

Pandas :从元组字典创建数据帧

S的两极是什么,相当于大Pandas 的`.ilo‘方法?

Python多处理池:缺少一个进程

如何在 python 中将带有时区信息的时间戳转换为 utc 时间

基于组/ID从原始数据框中创建两个子数据框

计算文档中所有关键字(单词和多词)出现的频率

如果集合大于 len(x),则 pandas 在重复的行中拆分集合列

如何沿单列获取嵌套列表中的唯一值?

单击图形时 plotly graph_objects 持久性数据

为什么 mypy 不适用于 sqlalchemy?

SqlAlchemy - 从 oracle db 中检索长文本

使用 python-binance 时,heroku [regex._regex_core.error: bad escape \d at position 7] 出错

如何从左到右解包元组?

pythondecorator中的变量范围

为什么包含类的名称不被识别为返回值函数注释?

pandas 中 df.reindex() 和 df.set_index() 方法的区别

通过多个键对字典列表进行分组和聚合

清除 PyCharm 运行窗口