2

我有一个函数,其参数的默认值为datetime.now(). 方法如下所示,

def as_standard_format(p_date=datetime.now(), fmt=sdk_constants.DEFAULT_DATE_TIME_FORMAT):
    return p_date.strftime(fmt)

我有一个类似下面的测试方法,

@freeze_time(datetime(year=2018, month=9, day=25, hour=15, minute=46, second=36))
def testNowWithDefaultFormat(self):

    # The below method gives the frozen time
    print(datetime.now())

    # But the below test fails
    assert utils.format_date(
        datetime.now()) == "20180925T154636Z", "Default call not giving current time in " \
                                               "standard format \"%Y%m%dT%H%M%SZ\""

为什么freeze_time不使用默认参数值?

4

1 回答 1

2

您正在成为 Python 中与可变默认值参数相关的常见问题的受害者,而不仅仅是特定于freeze_time.

对于解释,请考虑以下代码:

import time from datetime import datetime

def what_time_is_it(p_date=datetime.now()):
    return p_date.strftime('"%Y-%m-%d %X"')

if __name__ == '__main__':
    print(what_time_is_it())
    time.sleep(10)
    print(what_time_is_it())

您可能期望发生的事情

"2019-02-28 13:47:24"
"2019-02-28 13:47:34" # This line showing a datetime 10 seconds after the first one

datetime.now()每次调用都会调用一个新的what_time_is_it()

会发生什么

"2019-02-28 13:47:24"
"2019-02-28 13:47:24" # EXACTLY the same time in both lines!

定义函数时会创建一次新datetime.now()的,并且在每次后续调用中使用相同的值。

你应该怎么做?

每次调用函数时创建一个新对象,通过使用默认 arg 来表示未提供任何参数(None通常是一个不错的选择):

def as_standard_format(p_date=None, fmt=sdk_constants.DEFAULT_DATE_TIME_FORMAT):
    if p_date is None:
        return datetime.now().strftime(fmt)
    else:
        return p_date.strftime(fmt)
于 2019-02-28T17:29:39.700 回答