【问题标题】:Python variable weirdness?Python变量怪异?
【发布时间】:2010-09-01 14:52:58
【问题描述】:

我的 Python 变量发生了什么? old_pos 似乎与pos 相关联:

代码:

pos = [7, 7]
direction = [1, 1]
old_pos = pos
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)
pos[0] += direction[0]
pos[1] += direction[1]
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)

输出:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [8, 8]

但是,如果我将old_pos = pos 替换为old_pos = tuple(pos) 甚至old_pos = list(pos),我不会遇到这个问题:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [7, 7]

【问题讨论】:

  • 是的,= 就是这样做的。 :-)
  • python中没有变量,只有名称和对象。
  • @hop:但是名字不是引用变量吗?
  • @recursive:这取决于您如何定义“变量”,但如果您不认为 Python 名称与变量相同,通常会更容易考虑。见:python.net/crew/mwh/hacks/objectthink.html
  • “Python 中没有变量”是一个愚蠢而令人困惑的口号。您的意思是,“Python 中的变量的工作方式与 C 中的不同。”

标签: python list variables reference tuples


【解决方案1】:

当您说old_pos = pos 时,您并不是在创建pos 的副本,而只是对同一个列表进行了另一个引用。如果您想要两个独立运行的列表,则需要制作一个副本,例如使用您提到的 list(pos) 函数,或使用切片符号 pos[:]

【讨论】:

    【解决方案2】:

    old_pos = pos 不会创建由名称 pos 引用的对象的副本,而是为同一个对象创建名为 old_pos 的第二个引用。对pos 执行的操作会影响old_pos 引用的同一对象。同样,“史蒂文”和“伦巴尔斯基先生”这两个名字都指的是我。如果你打 Steven 的脸,Rumbalski 先生会受伤,因为这两个名字指的是同一个对象——我。

    这里有 3 种方法可以制作实际副本而不是第二个参考:

    使用切片表示法

    old_pos = pos[:]
    

    使用列表构造函数

    old_pos = list(pos)
    

    使用复制模块

    from copy import copy
    old_pos = copy(pos)
    

    请注意,这些副本都是浅副本,在这种情况下很好。要了解浅拷贝和深拷贝之间的区别,请阅读documentation of the copy module

    【讨论】:

      【解决方案3】:

      old_pos 似乎链接到pos

      正确 - 这个:

      old_pos = pos
      

      使old_pospos 指向同一个列表。它不会创建 pos 的新副本。

      【讨论】:

        【解决方案4】:

        递归是正确的原因。您可以看到它们具有相同的内存地址:

        >>> pos = [7, 7]
        >>> old_pos = pos
        >>> id(pos)
        4299304472
        >>> id(old_pos)
        4299304472
        

        这称为按引用传递,而不是按值传递。您也可以使用copy 模块来解决这种情况。

        >>> from copy import copy
        >>> pos = [7, 7]
        >>> old_pos = pos
        >>> id(pos)
        4299304472
        >>> id(old_pos)
        4299304472
        >>> old_pos = copy(pos)
        >>> id(old_pos)
        4299349240
        

        【讨论】:

        • 嗯...这并不是真正的通过引用传递,因为您没有在示例中传递任何内容。只是 Python 名称在引用 Python 对象时具有引用语义
        【解决方案5】:

        除了前面提到的 cmets 之外,在多维数组的情况下还必须采取一些额外的步骤。例如,当您有一个二维数组a = [[0,1,2],[3,4],[5,6,7,8]] 时,代码b = a 将不会创建一个独立的副本。但是,它将创建对二维列表中相同一维列表的引用的另一个引用。要解决此问题,您必须对二维列表中的每个列表使用上述方法之一。例如,b = [i[:] for i in a] 将创建列表的独立副本。

        【讨论】:

          猜你喜欢
          • 2011-01-11
          • 2012-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多