Python 函数调用之间未重新分配集合

Python 函数调用之间未重新分配集合,python,python-3.x,scope,set,Python,Python 3.x,Scope,Set,在我的例子中,我尝试在递归函数调用和更新之间传递一个集合。通过每次将其作为参数显式传递,我希望集合在递归期间保持更新 对于一个新的调用,我没有明确地传递set a参数,并期望res\u set的引用将重定向到一个空的set对象。但是在多次调用该函数时,该集合将被更新,就好像不存在res\u set=set()一样 def some_recursion_withset(i, res_set = set()): res_set.add(random()) if i

在我的例子中,我尝试在递归函数调用和更新之间传递一个集合。通过每次将其作为参数显式传递,我希望集合在递归期间保持更新

对于一个新的调用,我没有明确地传递set a参数,并期望
res\u set
的引用将重定向到一个空的set对象。但是在多次调用该函数时,该集合将被更新,就好像不存在
res\u 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}
{0.9691623786355451}
{0.9691623786355451, 0.37884137576633103}
{0.9691623786355451, 0.37884137576633103, 0.4482797349507742}
简化为一个最小的工作示例,为什么在这种情况下会忽略
res\u 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.12513618559206574}
{0.12513618559206574, 0.8224507177489353}
{0.12513618559206574, 0.8224507177489353, 0.7157637106872556}
{0.12513618559206574, 0.8224507177489353, 0.6921901499074943, 0.7157637106872556, 0.8116969360080692}
{0.9691623786355451}
{0.9691623786355451, 0.37884137576633103}
{0.9691623786355451, 0.37884137576633103, 0.4482797349507742}
我最感兴趣的是了解这种行为以及实现第一个递归部分的一些良好实践。

来自:

默认值仅计算一次。这会使情况有所不同 这个 默认为可变对象,如列表、字典或most的实例 上课。例如,以下函数累加传递给的参数 在随后的电话中:

res\u set=set()
只计算一次,这是默认参数,在您的例子中是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

因此,如果我理解正确,实现我想要的递归功能的最佳方法是(“根据手册”):
def(some\u recursion\u with set,res\u set=None):
并检查
res\u set
是否准确无误。请注意,使用
的测试是
测试对象标识。由于Python实例只有一个
None
对象,每当使用
None
时都会插入该对象,因此可以使用
is
来查看参数是这一个
None
对象还是其他对象。它起作用了。非常感谢您的帮助:)您确定理解正确吗?你所说的是‘如果我传入一个
resu set
参数,那么使用它,如果没有,那么使用
set()
。这并不意味着每次调用时都要创建一个新的集合,它只是意味着如果一个新集合没有传递给函数,就使用它作为默认值。