繁体   English   中英

列出Python中的引用混淆

[英]List pass by reference confusion in Python

我有一段代码,只对保证在0到R-1(含)之间的数字列表进行排序。 以下代码正确地进行了排序,但是我不明白为什么传入的输入保持不变。

def bucket(arr, R):
    assert type(arr) is list
    for i in arr:
        assert i >=0 and i < R
    b = [0] * R
    for i in arr:
        b[i]+=1
    arr = []
    for ind, v in enumerate(b):
        arr = arr + [ind] * v
    print(arr)

为什么在此示例中inp在调用函数后没有发生变化:

>>> inp
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp # unchanged, why?
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]

因为您在arr = []行中创建了一个名为arr的新变量,并且从这一点开始,您将对新列表进行操作。 同样,你永远是以下中创建新的列表for -loop与arr = arr + [ind] * v操作。

您可以将其更改为:

def bucket(arr, R):
    assert type(arr) is list
    for i in arr:
        assert i >= 0 and i < R
    b = [0] * R
    for i in arr:
        b[i] += 1
    arr[:] = []  # remove all items from the list (in-place)
    for ind, v in enumerate(b):
        arr.extend([ind] * v)  # extend the list in-place, you could also use "arr += [ind] * v"
    print(arr)

例:

>>> inp = [3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]

通过将[]分配给arr您将丢失对现有数组的引用,并创建一个新数组。

要更改它,您可以使用

inp.sort()

有关排序与排序的更多信息

Python通过赋值传递,其语义与Java的值传递极为相似。

之所以会出现混乱,是因为您正在按值传递指针 这意味着您不能在函数内部修改指针,但是没有人可以阻止您修改指针指向的内容 (即数据)。因此,例如:

x = 3
def change_x(x):
    x = 5
    return x
change_x(x)
print x
# Outputs 3

函数外部的x值(在本例中为3)在x进入函数之前已被复制,因此赋值不执行任何操作。 这通常是我们听到按值传递时所期望的结果。

x = [1,2,3]
print(id(x))
# Outputs some "address"
def change_x(x):
    x.clear()
    x.extend([4,5,6])
    print(id(x))
    # Outputs the SAME address as above
    return x
change_x(x)
print(x)
# Outputs [4,5,6]

有没有搞错。 我以为我们只是说我们不能改变x。 问题是我们没有改变x! 我们只是更改了x指向的数据(此处存在细微但重要的区别)。 x仍然是相同的指针。 请注意,由id输出的地址是相同的。

x = [1,2,3]
print(id(x))
# Outputs some "address"
def change_x(x):
    x = [4,5,6]
    print(id(x))
    # Outputs some DIFFERENT "address". The pointer to x was changed (inside this function).
    return x
change_x(x)
print(x)
# Outputs [1,2,3]

它在传递x之前复制了x的值(复制了指针值,而不是数据)。 因此,再分配也无济于事。 注意,这次id函数输出不同的值。 因此,在函数返回之后,我们得到x的原始值(即指针的原始值)

暂无
暂无

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

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