在 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]
).
您能否解释一下出现这种 mixed 行为的原因?
我试图探索工作的东西如下:
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']
我注意到,当我通过 使用索引 更改函数内部列表的值时, actual 列表发生了变化.否则列表不受影响。
任何帮助表示赞赏。
a[:-1]
创建一个新列表,然后你将它传递下去
您的函数没有 return 值,它依赖于可变列表才能就地更改。但是,您随后使用当前列表的一部分调用递归,这会生成一个副本(因此生成一个新列表),因此不再引用列表 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]
一个解决方案是包含一个 return 调用。
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]
当我 运行 遇到这个问题时,我正尝试使用递归编写冒泡排序代码。
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]
).
您能否解释一下出现这种 mixed 行为的原因?
我试图探索工作的东西如下:
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']
我注意到,当我通过 使用索引 更改函数内部列表的值时, actual 列表发生了变化.否则列表不受影响。 任何帮助表示赞赏。
a[:-1]
创建一个新列表,然后你将它传递下去
您的函数没有 return 值,它依赖于可变列表才能就地更改。但是,您随后使用当前列表的一部分调用递归,这会生成一个副本(因此生成一个新列表),因此不再引用列表 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]
一个解决方案是包含一个 return 调用。
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]