Set 未在函数调用之间重新分配

Set is not being reasigned between function calls

在我的例子中,我尝试在递归函数调用和更新它之间传递一个集合。通过每次都明确地将其作为参数传递,我希望该集合在递归期间不断更新。

对于一个新调用,我没有明确地传递一个参数集,并期望 res_set 的引用将重定向到一个空集对象。但是在多次调用该函数后,该集合正在更新,就好像 res_set = set() 不存在一样。

 def some_recursion_withset(i, res_set = set()):
        res_set.add(random())
        if i > 0:
            i -= 1
            print(res_set)
            some_recursion_withset(i, res_set)
        return res_set

    some_recursion_withset(3)
    some_recursion_withset(1)

这里的输出是:

{0.12513618559206574}
{0.12513618559206574, 0.8224507177489353}
{0.12513618559206574, 0.8224507177489353, 0.7157637106872556}
{0.12513618559206574, 0.8224507177489353, 0.6921901499074943, 0.7157637106872556, 0.8116969360080692}

减少到最小的工作示例,为什么在这种情况下 res_set = set() 被忽略?

from random import random

def some_func_withset(res_set = set()):
    res_set.add(random())
    return res_set

print(some_func_withset())
print(some_func_withset())
print(some_func_withset())

在这种情况下输出是:

{0.9691623786355451}
{0.9691623786355451, 0.37884137576633103}
{0.9691623786355451, 0.37884137576633103, 0.4482797349507742}

我最感兴趣的是了解这种行为以及实现第一个递归部分的一些良好做法。

来自Python tutorial

The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

res_set = set() 只计算一次,这是默认参数,在你的例子中是一个集合对象。当您使用带有默认参数的函数时,您总是得到相同的集合对象,并且由于您不断更新它,该集合会随着您插入的所有值而增长。

你的问题的一个解决方案是使用一个不可变对象作为金丝雀,然后检查你的参数是否是这个金丝雀。如果是这种情况,则创建一个新集。在这种情况下使用 None 是 Python 程序员的惯例:

def some_func_withset(res_set = None):
    if res_set is None:
        res_set = set()
    res_set.add(random())
    return res_set