【问题标题】:Why operating with list gives different results?为什么使用列表操作会产生不同的结果?
【发布时间】:2020-02-01 18:01:06
【问题描述】:

所以我正在使用 Jacobi 算法来近似方程组的解,并且在使用列表时遇到了一些我不理解的事情。 假设我有这三个功能

def func1 (list):
    list_old = list
    list[0] = 99

    print(list_old)
    print(list)

def func2 (list):
    list_old = list.copy()
    list[0] = 99

    print(list_old)
    print(list)

def func3 (list):
    list_old = list
    list = [9,9,9]

    print(list_old)
    print(list)

list = [0,0,0]
func1(list)
func2(list)
func3(list)

Func1 打印

[99, 0, 0] # List_old
[99, 0, 0] # List

Func2 打印

[0, 0, 0] # List_old
[99, 0, 0] # List

Func3 打印

[0, 0, 0] # List_old
[9, 9, 9] # List

所以我的问题是: 1) 为什么 func1 处的 List[0] 会修改 list_old?我认为它与指针和内存空间有关,但我不确定,我没有找到任何解释这一点的东西。 2) 为什么在 func3 list_old 中不修改?不应该和func1一样吗?

【问题讨论】:

  • 命名变量list 会覆盖内置函数。 func1 有两个变量指向同一个内存位置。 func2 显然做了一个副本,两个不同的变量指向不同的内存位置。 func3list 重新分配到新的内存位置,但 list_old 仍指向原始的 list 位置,因此不会发生混叠。
  • 阅读关于可变和不可变python类型的信息medium.com/@meghamohan/…

标签: python list


【解决方案1】:

@ggorlen 所说的几乎是正确的。 Python 变量(如列表)的工作方式是将它们存储在内存中的特定点。通过将列表变量传递给函数,然后对其进行修改,您正在修改它在内存中的特定地址,因此即使您离开函数 func1 例如,您也修改了原始列表,并且对它的调用将进行这些修改。

您在 func2 中使用 .copy() 所做的是在内存中的另一个点创建另一个列表。因此,对此列表的修改不会影响对原始列表的修改,反之亦然(也就是说,func1 中的修改仍将存在于新复制的列表中,因为它们是在复制之前进行的)。

现在,回答您的问题,在 func1 中的 list_old 与 func2 中的 list_old 不同,变量名 list_old 对于函数 func1 和 func2 都是本地的,并且指向不同的列表。 func1 中的 list_old 指向在函数之外的第一行代码中声明的原始列表。 func2 中的 list_old 指向一个新创建的副本,这两个变量是不同的。在 func3 list_old = list 将 list_old 分配给原始列表,但是您有 list = [9,9,9] 它创建了一个新列表,因此在内存中有一个新地址。因此, func3 中的 list_old 和 list 指向两个记忆中不同的地方。

这是一篇关于python中变量的好帖子https://medium.com/@tyastropheus/tricky-python-ii-parameter-passing-for-mutable-immutable-objects-10e968cbda35

【讨论】:

    【解决方案2】:

    正如@Dmitry 指出的关于不变性和可变性的那样,列表类型与python 中的其他类型不同的是可变的,这意味着对列表的操作会改变列表本身,而其他不可变对象(如字符串)在操作时会在内存中创建新实例.下面的代码更好地说明了这一点:

    lstA = [0, 0, 0]
    lstB = lstA
    print(lstA is lstB) # True
    # change list B
    lstB[0] = 9
    print(lstA is lstB) # keeps True
    strA = "A string"
    strB = strA
    print(strA is strB) # True
    # Change strB
    srtB[0] = "B" # Ops! item assignment not supported (immutable object)
    # Then let's do it in another way
    strB = "B" + strA[1:] # strB = "B string"
    print(strA is strN) # False (other string was created)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 2017-02-21
      相关资源
      最近更新 更多