在Python中解决默认参数静态值的模式

huangapple go评论61阅读模式
英文:

Pattern to work around the static value of a python default argument

问题

Python有一个令人惊叹的特性,即默认参数在函数/方法定义时只会被评估一次:

from datetime import datetime
import time
def some_func(ts: datetime = datetime.now()):
    print("现在是什么时间?", ts)

some_func()
time.sleep(5)   # 等待5秒
some_func()

输出结果:

现在是什么时间 2023-08-08 18:43:43.697853
现在是什么时间 2023-08-08 18:43:43.697853

是的,这种行为是有文档记录的。这也超出了我之前在八十年代以来使用过的几十种语言的经验范围。更近期的语言,如Scala(以及之前的Java),肯定不会采用这种方式。是否有任何模式可以实现在调用时评估默认值的相同结果?

英文:

Python has this stunning characteristic that default parameters are evaluated once - at the time the function/method is defined:

from datetime import datetime
import time
def some_func(ts: datetime = datetime.now()):
    print("What time is it 'now'?",ts)

some_func()
time.sleep(5)   # sleeps 5 seconds
some_func()

Prints:

What time is it 'now'? 2023-08-08 18:43:43.697853
What time is it 'now'? 2023-08-08 18:43:43.697853

Yes this behavior is documented. It is also beyond my prior experience having worked in dozens of languages since the early eighties. More recent languages such as scala (and java before that) certainly do not take that angle on it. Is there any pattern to use that can achieve the same result as evaluating default values at invocation time ?

答案1

得分: 3

这个问题也会出现在可变的默认参数中。解决方法是相同的:使用一个特殊值作为默认参数(例如None),然后在函数体中进行检查:

def some_func(ts: datetime=None):
    if ts is None:
        ts = datetime.now()
    print("现在是什么时间?", ts)
英文:

This problem also arises with mutable default arguments. The solution is the same: Use a sentinel value for the default argument (e.g. None), then check for it in the function body:

def some_func(ts: datetime=None):
    if ts is None:
        ts = datetime.now()
    print("What time is it 'now'?",ts)

答案2

得分: 2

将默认值设置为None。

然后添加一个保护子句,如果参数为None,则将值设置为您的动态默认值。

当您希望默认参数是空列表、字典或其他集合时,这一点尤为重要。

from datetime import datetime
import time
def some_func(ts: datetime = None):
    if ts is None:
        ts=datetime.now()
    print("现在是几点了?",ts)

some_func()
time.sleep(5)   # 等待5秒钟
some_func()

输出

现在是几点了? 2023-08-08 21:07:07.692347
现在是几点了? 2023-08-08 21:07:12.697683
英文:

Set the default to None.

Then add a guard clause to set the value to your dynamic default value if the parameter is None.

This is especially important when you want the default parameter to be an empty list, dict, or other collection.

from datetime import datetime
import time
def some_func(ts: datetime = None):
    if ts is None:
        ts=datetime.now()
    print("What time is it 'now'?",ts)

some_func()
time.sleep(5)   # sleeps 5 seconds
some_func()

Output

What time is it 'now'? 2023-08-08 21:07:07.692347
What time is it 'now'? 2023-08-08 21:07:12.697683

huangapple
  • 本文由 发表于 2023年8月9日 09:48:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76864083.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定