有点蟒蛇新手,所以请耐心等待我。我在python中有两个代码片段:
def summer(step, track, lst):
if track<10:
lst.append(1)
summer(step,track+step,lst)
return lst
调用summer(1,1,[])返回
[1, 1, 1, 1, 1, 1, 1, 1, 1]
现在我要说:
def summer(step, track):
if track<10:
track +=step
summer(step,track)
return track
调用summer(1,1)返回2
注意这两个片段之间的相似性,在第一个片段中,我将附加到列表中,最后返回该列表。它按预期工作。
在第二个中,我改为增加变量,但最后当我返回它时,它不能按预期工作(当它应该返回11时返回2)。我理解这是因为在第二个片段中我递归调用
summer(step,track)
我什么时候该说
return summer(step,track)
但为什么在第一个片段中,我可以简单地调用
summer(step,track+step,lst)
而不是
return summer(step,track+step,lst)
它仍然有效吗?即,跟踪列表和递归中的int似乎有不同的处理方式?
答案 0 :(得分:6)
不同之处在于列表是可变的,而int则不是。这条线
lst.append(1)
修改lst
引用的对象。这条线
track += step
与track = track + step
相同,因为track
指的是不可变对象(int
)。因此,本地名称track
只是设置为一个新对象,而不是以某种方式修改作为参数传递给summer()
的对象。
虽然+=
打算是一个就地操作符,但没有严格要求它是这样的。 int.__iadd__
正好返回一个新的int
对象,因为int
是不可变的,因此无法对其进行修改。
答案 1 :(得分:1)
因此list
不作为值传递,而int
则是。{{1}}。所以你正在修改递归调用中的实际列表,而调用之前的int与递归调用中修改的int不同。
答案 2 :(得分:0)
@chepner已经提供了一个很好的解释来证明可观察行为的差异。另一方面,我想谈谈你可以使用的两种模式,这些模式将来在使用可变/ im-mutable变量时会留下更少的混淆。
>>> def summer(step, track, lst):
if track<10:
return summer(step,track+step,lst + [1])
else:
# Trivial Case
return lst
>>> summer(1,1,[])
[1, 1, 1, 1, 1, 1, 1, 1, 1]
>>>
>>> def summer(step, track):
if track<10:
return summer(step,track + step)
else:
# Trivial Case
return track
>>> summer (1,1)
10
正如您所看到的,两种方法看起来非常相似,对可变对象和不可变对象没有单独处理,并且准确地返回结果。
因此,需要注意的重要事项是,以递归模式,