代码之家  ›  专栏  ›  技术社区  ›  pipsqueaker117

Python中计算为相等的非等效变量

  •  2
  • pipsqueaker117  · 技术社区  · 12 年前

    因此,在测试一些代码时,我发现Python中有一些奇怪的功能,即两个值不同的变量求值相等。产生所述行为的代码如下

    class Foo:
        def __init__(self):
            self.x = [1,2,3]
            self.y = self.x
    
        def ChangeX(self):
            self.x.append(4)
    
        def equals(self):
            print(self.x==self.y)
    

    当我运行这段代码时,变量会按照它们应该的方式初始化。如果我跑

    f = Foo()
    f.equals()
    

    输出为True,我可以理解,因为此时f.x和f.y都保持相同的值。然而,当我跑步时

    r = Foo()
    r.ChangeX()
    r.equals()
    

    输出仍然为真。这让我很困惑。r.x和r.y显然不再持有相同的值(按顺序打印它们甚至会产生不同的输出),但Python似乎认为这两个变量彼此相等。

    我有一种预感,这与我正在使用一个类有关;然而,我仍然不知道这里到底发生了什么,或者如何“修复”它。有人能解释一下吗?

    4 回复  |  直到 12 年前
        1
  •  3
  •   user2555451 user2555451    12 年前

    self.x self.y 两者都引用内存中的同一列表对象。也就是说,当你更新其中一个时,另一个将反映变化。

    您可以在下面的演示中看到这种行为:

    >>> a = [1, 2, 3]
    >>> b = a
    >>>
    >>> # The contents of a and b are the same
    >>> a
    [1, 2, 3]
    >>> b
    [1, 2, 3]
    >>>
    >>> # And their ids are the same
    >>> id(a)
    33908856
    >>> id(b)
    33908856
    >>>
    >>> a.append(4)
    >>> a
    [1, 2, 3, 4]
    >>> b
    [1, 2, 3, 4]
    >>>
    

    如果要更改此行为,可以指定 自我。y 自身.x :

    self.y = self.x[:]
    

    请参见下面的演示:

    >>> a = [1,2,3]
    >>> b = a[:]
    >>>
    >>> # The contents of a and b are the same
    >>> a
    [1, 2, 3]
    >>> b
    [1, 2, 3]
    >>>
    >>> # But their ids are different
    >>> id(a)
    33984680
    >>> id(b)
    33984960
    >>>
    >>> a.append(4)
    >>> a
    [1, 2, 3, 4]
    >>> b
    [1, 2, 3]
    >>>
    
        2
  •  2
  •   leeladam    12 年前

    你没有两个列表。你有一个列表 x 以及对列表的引用 x(x) 已调用列表 y 。当您修改列表x时,引用y后面的值也会被修改。了解更多信息 here .

        3
  •  1
  •   Graeme Stuart    12 年前

    self.x self.y 参考相同的数据。当你这样做的时候

    self.y = self.x
    

    将两个变量绑定到内存中的同一数组。

    如果你想让它们与众不同,最好这样做

    self.y = list(self.x)
    
        4
  •  0
  •   Ruben Bermudez    12 年前

    正如你所看到的, self.y = self.x 正在分配给 y 引用 x :

    class Foo:
        def __init__(self):
            self.x = [1,2,3]
            self.y = self.x
    
        def ChangeX(self):
            self.x.append(4)
    
        def equals(self):
            print(self.x==self.y)
    
    
    f = Foo()
    f.equals()
    f.ChangeX()
    f.equals()
    print(f.x)
    print(f.y)
    #True
    #True
    #[1, 2, 3, 4]
    #[1, 2, 3, 4]