TL;DR Python的默认参数实现机制很容易导致难以调试的bug。正确的使用方法是避免使用可变类型作为默认参数。

默认可变参数带来的问题

函数的默认参数如果是可变类型的变量,可能会带来难以debug的bug。def定义的函数,在解释器定义为函数时,会计算默认参数的值,并将值存储在 func_defaults 属性中,并且该默认值只会初始化一次

    def append_to_list(item, list_=[]):
        list_.append(item)
        print(list_)

    print(".func_defaults:", append_to_list.func_defaults)
    append_to_list(0)
    print(".func_defaults:", append_to_list.func_defaults)
    append_to_list(1)
    print(".func_defaults:", append_to_list.func_defaults)

运行以上代码,则会有如下输出:

('.func_defaults:', ([],))
[0]
('.func_defaults:', ([0],))
[0, 1]
('.func_defaults:', ([0, 1],))

解决方案

    def append_to_list(item, list_=None):
        if list_ is None:
            list_ = []
        list_.append(item)
        print(list_)

    print(".func_defaults:", append_to_list.func_defaults)
    append_to_list(0)
    print(".func_defaults:", append_to_list.func_defaults)
    append_to_list(1)
    print(".func_defaults:", append_to_list.func_defaults)

运行以上代码,则会有如下输出:

    ('.func_defaults:', (None,))
    [0]
    ('.func_defaults:', (None,))
    [1]
    ('.func_defaults:', (None,))

参考

  1. 编写高质量Python代码的91个建议 第32个建议