繁体   English   中英

在 Python3 中将列表作为参数传递是如何工作的?

[英]How does passing a list as an argument work in Python3?

当我遇到这个问题时,我试图使用递归对冒泡排序进行编码。

def bubble_sort_recur(a):
    print(a)
    if len(a)==1:
        return
    for i in range(len(a)-1):
        if a[i] > a[i+1] :
            a[i]=a[i]^a[i+1] # swap using XOR
            a[i+1]=a[i]^a[i+1]
            a[i]=a[i]^a[i+1]
    print(a) # shows the changes made in the current call
    bubble_sort_recur(a[:-1])

b=[1,6,1,66,3,32,21,33,1] # initial list
bubble_sort_recur(b) # function call

我认为python对对象(列表)使用按对象引用传递。 递归的输出也是预期的,如下:

[1, 6, 1, 66, 3, 32, 21, 33, 1]
[1, 1, 6, 3, 32, 21, 33, 1, 66] # 66 bubbles up
[1, 1, 6, 3, 32, 21, 33, 1]
[1, 1, 3, 6, 21, 32, 1, 33]
[1, 1, 3, 6, 21, 32, 1]
[1, 1, 3, 6, 21, 1, 32]
[1, 1, 3, 6, 21, 1]
[1, 1, 3, 6, 1, 21]
[1, 1, 3, 6, 1]
[1, 1, 3, 1, 6]
[1, 1, 3, 1]
[1, 1, 1, 3]
[1, 1, 1]
[1, 1, 1]
[1, 1]
[1, 1]
[1]

可以看到第三个“1”如预期的那样冒泡到第二个索引。 但是当我做print(b)我得到[1, 1, 6, 3, 32, 21, 33, 1, 66]这既不是排序列表也不是原始列表b=[1,6,1,66,3,32,21,33,1] )。 你能解释一下这种混合行为的原因吗? 我试图探索的工作如下:

def func(a):
    a[0]='only one altered'
def func2(b):
    a=['this','is', 'completely', 'new']
a=[1,'initial',2, 'array']
func(a) # this changes the list
print(a)
func2(a) # this does not change the list 'a' , in any way.
print(a)
>> ['only one altered', 'initial', 2, 'array']
   ['only one altered', 'initial', 2, 'array']

我注意到,当我使用索引更改函数内部列表的值时,实际列表会发生变化。 否则列表不受影响。 任何帮助表示赞赏。

您的函数不返回值,并且依赖于可变列表以使其就地更改。 但是,您随后使用当前列表的一个切片调用递归,这会生成一个副本(因此是一个新列表),因此不再引用列表b

您可以通过在递归之前添加print(b)行来验证这一点。

def bubble_sort_recur(a):
    print(a)
    if len(a)==1:
        return
    for i in range(len(a)-1):
        if a[i] > a[i+1] :
            a[i]=a[i]^a[i+1] # swap using XOR
            a[i+1]=a[i]^a[i+1]
            a[i]=a[i]^a[i+1]
    print(a) # shows the changes made in the current call
    print(b)
    print()
    bubble_sort_recur(a[:-1])

b=[1,6,1,66,3,32,21,33,1] # initial list
bubble_sort_recur(b) # function call

输出

[1, 6, 1, 66, 3, 32, 21, 33, 1]
[1, 1, 6, 3, 32, 21, 33, 1, 66]
[1, 1, 6, 3, 32, 21, 33, 1, 66] # first call changed b

[1, 1, 6, 3, 32, 21, 33, 1]
[1, 1, 3, 6, 21, 32, 1, 33]
[1, 1, 6, 3, 32, 21, 33, 1, 66] # none of the recursions changed b

[1, 1, 3, 6, 21, 32, 1]
[1, 1, 3, 6, 21, 1, 32]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1, 1, 3, 6, 21, 1]
[1, 1, 3, 6, 1, 21]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1, 1, 3, 6, 1]
[1, 1, 3, 1, 6]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1, 1, 3, 1]
[1, 1, 1, 3]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1, 1, 1]
[1, 1, 1]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1, 1]
[1, 1]
[1, 1, 6, 3, 32, 21, 33, 1, 66]

[1]

一种解决方案是包括返回调用。

def bubble_sort_recur(a):
    if len(a) > 1:
        for i in range(len(a)-1):
            if a[i] > a[i+1] :
                a[i], a[i+1] = a[i+1], a[i] # more pythonic syntax
                # or
                # a[i:i+2] = a[i+1:i-1:-1]
                # or your original code
                # a[i]=a[i]^a[i+1] # swap using XOR
                # a[i+1]=a[i]^a[i+1]
                # a[i]=a[i]^a[i+1]
        print(a)
        a[:-1] = bubble_sort_recur(a[:-1]) # catch the result of recursion
    return a

b = [1,6,1,66,3,32,21,33,1] # initial list
b = bubble_sort_recur(b) # function call
[1, 1, 6, 3, 32, 21, 33, 1, 66]
[1, 1, 3, 6, 21, 32, 1, 33]
[1, 1, 3, 6, 21, 1, 32]
[1, 1, 3, 6, 1, 21]
[1, 1, 3, 1, 6]
[1, 1, 1, 3]
[1, 1, 1]
[1, 1]

>>> print(b)
[1, 1, 1, 3, 6, 21, 32, 33, 66]

a[:-1]创建一个新列表,然后将其向下传递

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM