带有可变函数的函数参数,避免“if arg is None”构造

Function argument with mutables, avoid `if arg is None` construct

提问人:Wör Du Schnaffzig 提问时间:10/25/2021 更新时间:10/25/2021 访问量:139

问:

有没有办法避免像下面这样的重复代码?对 20 个其他函数进行成像,这些函数采用具有默认值的可变参数。 每次检查参数时,每次在分支中分配默认值。 将默认值放在函数签名中不起作用,因为 python 会在首次调用函数时缓存该值。Noneif

import datetime as dt

def dt_to_str(dtime: dt.datetime = None):
    if dtime is None:
        dtime = dt.datetime.now()

    return dtime.strftime("%c")


if __name__ == '__main__':
    print(dt_to_str())
python-3.x 违约 可变

评论

0赞 ddejohn 10/25/2021
你可以写一个装饰器,但这可能不值得付出努力。您能提供有关您的实际用例的更多详细信息吗?
0赞 ddejohn 10/25/2021
你所有的函数都遵循相同的模式:块内的单个函数调用,返回中的单个函数调用?if
0赞 Wör Du Schnaffzig 10/25/2021
我有几种情况可以使用默认参数将两个函数重构为一个函数。一个函数不接受参数,另一个函数接受一个参数,但做同样的事情。因此,如果它们具有默认参数,则它们可能是一个函数。为所有这些提供解决方法是相当乏味的。我只想有一个更通用的解决方案,我可以为函数提供可变的默认值,而无需为每个默认值编写两行额外的重复代码。也许提供装饰器并不是一个坏主意。None

答:

1赞 kaya3 10/25/2021 #1

我认为在大多数情况下,语法是最好的解决方案。但是,如果您真的对此感到困扰,这里有一个适用于单参数函数的装饰器:if arg is None: arg = ...

from functools import wraps

def default_argument(arg_factory):
    def decorator(f):
        @wraps(f)
        def wrapped(arg=None):
            if arg is None:
                arg = arg_factory()
            return f(arg)
        return wrapped
    return decorator

用法示例如下:可以传递对现有函数的引用,也可以传递 .lambda

import datetime as dt

@default_argument(dt.datetime.now)
def dt_to_str(dtime):
    return dtime.strftime('%c')

print(dt_to_str())
# Mon Oct 25 00:16:03 2021

@default_argument(lambda: [])
def thing_with_list(lst):
    return lst + [123]

print(thing_with_list())
# [123]