在Python中可以使用模块常量作为默认函数参数吗?

gmo*_*lau 5 python function function-parameter

基本上是这样的:

DEFAULT_TIMEOUT = 10
# or even: from my_settings import DEFAULT_TIMEOUT

def get_google(timeout=DEFAULT_TIMEOUT):
    return requests.get('google.com', timeout=timeout)
Run Code Online (Sandbox Code Playgroud)

我认为只要常数确实保持不变,就应该可以正常工作。但我有时会看到这样的模式:

DEFAULT_TIMEOUT = 10

def get_google(timeout=None):
    if timeout is None:
        timeout = DEFAULT_TIMEOUT
    return requests.get('google.com', timeout=timeout)
Run Code Online (Sandbox Code Playgroud)

这些是等效的还是我应该更喜欢其中一个?

Bre*_*arn 5

使用“常量”作为默认值没有问题。正如你所说,只要“常数”确实是常数,那就没关系。唯一的事情是,您必须确保常量是在函数之前定义的,但通常人们将所有常量放在文件的顶部,因此这不是问题。

当所需的默认值是可变值(例如列表)时,您描述的第二种模式很常见。你经常会看到这样的事情:

def foo(x=None):
    if x is None:
        x = []
Run Code Online (Sandbox Code Playgroud)

代替def foo(x=[])。您可能会发现很多与此相关的问题,但本质上是因为如果您不这样做,则可变默认值将在对该函数的多次调用中持续存在,这通常是不可取的。

但是,将此模式用于可变模块级常量并不能解决该问题。如果你有:

SOME_CONSTANT = []

def foo(x=None):
    if x is None:
        x = SOME_CONSTANT
Run Code Online (Sandbox Code Playgroud)

。。。那么您仍然在多个调用中重用相同的可变值。(当然,将可变值定义为“常量”可能不是一个好主意。)这就是为什么我在评论中询问您是否见过有人专门用模块常量做这种事情。

如果模块级默认值实际上不是常量,而是打算由其他代码更改的值,则也可以使用此 None-then-if 模式。如果这样做def foo(x=DEFAULT_TIMEOUT),则 的默认值x定义DEFAULT_TIMEOUT该函数时的值。但如果您使用 None-then-if 模式,则默认值将是您调用该函数时的任何值。某些库定义的模块级值并不意味着是常量,而是可能在执行过程中更改的配置值。这允许用户执行诸如设置更改所有后续调用的默认超时之类的操作,而不必每次都通过。在这种情况下,您需要在函数内部进行 if 检查,以确保每次调用都使用 的“当前”值。DEFAULT_TIMEOUTDEFAULT_TIMEOUT = 20timeout=20DEFAULT_TIMEOUT