python 非 None 默认值

4 投票
2 回答
2671 浏览
提问于 2025-04-18 06:38

程序员A写了一个函数:

def compute_value(threshold = sys.float_info.max):
   ...
   return value

这个函数有一个可选参数threshold,默认值是一个很大的浮点数,表示“没有阈值”。

程序员B也有一个阈值的表示方法,但他用None来表示没有阈值。不幸的是,当threshold为None时,compute_value函数不会抛出任何异常,但会给出错误的答案。因此,当程序员B传入None作为阈值时,就出现了一个bug。

我认为最好的解决办法是修改这个函数:

def compute_value(threshold = None):
    if threshold is None:
        threshold = sys.float_info.max
    ...
    return value

因为这个函数比之前更通用,它以一种合理的方式处理None值。

这就引出了一个问题:是否总是最好只使用None作为默认值?

这并不是我第一次遇到默认参数不是None而导致麻烦的情况。在其他情况下,我发现自己需要从kwargs字典中移除None值……

还有一个相关的(可能有点傻)问题。实际上,程序员B将上面的函数修改成了这样:

def compute_value(threshold = sys.float_info.max):
    if threshold is None:
        threshold = sys.float_info.max
    ...
    return value

这个修改是完全正确的,但我觉得看起来不太好。不好是因为sys.float_info.max重复了两次……但是:这算不算违反了DRY原则?因为严格来说,在第一个实现中,None也重复了两次,而None和sys.float_info.max都是常量。

2 个回答

1

你还可以通过使用kwargs来解决None作为默认值的问题。

def compute_value(**kwargs):
    threshold = kwargs.get('threshold', sys.float_info.max)
    ...
    return value
5

这其实就是在问你(作为API提供者)是否认为None可以作为一个有效的参数传给这个函数。就我个人而言,在这种情况下,我觉得我会使用sys.float_info.max,并且不允许使用None。毕竟,None为什么要假装成一个float呢?None作为默认参数的标准用法是当你需要一个可变的默认参数,但在这里并不是这种情况。

不过,也可以反过来说——如果你使用None,那么help会告诉你阈值是None,从“把代码当文本看”的角度来看,这也有点道理。(毕竟,这意味着没有阈值)。1

不过最终,这其实只是斤斤计较罢了。选择一个约定,记录下来并坚持使用。别太担心这个问题。


1如果你有自动生成的文档(比如sphinx),而且sys.float_info.max在生成文档的电脑上返回的值和运行代码的电脑上不一样,这种情况就更糟糕了。这个场景其实不太可能发生——现在大多数电脑都遵循IEEE标准,但……

撰写回答