python如何在赋值运算符后赋值

时间:2015-12-30 00:04:53

标签: python python-2.7 python-3.x python-internals

我确定,这是一个非常愚蠢的问题。但是python如何为变量赋值?

假设存在变量a=2并为其分配值a。所以python为变量分配一个内存位置,2现在指向包含值b=a的内存位置。现在,如果我分配变量b,变量a也指向与变量c=2相同的位置。

现在。如果我分配变量a,它仍然指向与a=[2,3]相同的内存位置,而不是指向新的内存位置。那么,python是如何工作的?它是否首先检查所有先前分配的变量,以检查它们中的任何一个是否共享相同的值,然后为其分配内存位置?

此外,它与列表的工作方式不同。如果我分配b=[2,3]然后id并使用c=b函数检查其内存位置,我会得到两个不同的内存位置。但是is给了我相同的位置。有人可以解释正确的工作和原因吗?

编辑: -

基本上我的问题是因为我刚刚开始了解True运算符,并且只有当它们指向同一位置时才会显示它a=1000。因此,如果b=1000a is b Falsea="world"b="world" $ sed -r '1s/([a-zA-Z]:)0/\199999/' file root:cDJZp9SHD2KhVgc:99999:0:99999:7::: bin:*:12821:0:99999:7::: daemon:*:12811:0:99999:7::: adm:*:12811:0:99999:7::: lp:*:12811:0:99999:7::: 则为真。

3 个答案:

答案 0 :(得分:7)

我之前遇到过这个问题,并且明白它会让人感到困惑。这里有两个概念:

  1. 某些数据结构是可变的,而其他数据结构则不是
  2. Python在指针上工作......大部分时间
  3. 所以让我们考虑列表的情况(当你使用整数时,你不小心偶然发现了实习和窥视孔的优化 - 我稍后会谈到这一点)

    因此,让我们创建两个相同的列表(记住列表是可变的)

    In [42]: a = [1,2]
    
    In [43]: b = [1,2]
    
    In [44]: id(a) == id(b)
    Out[44]: False
    
    In [45]: a is b
    Out[45]: False
    

    尽管列表相同,但ab是不同的内存位置。现在,这是因为python计算[1,2],将其分配到内存位置,然后调用该位置a(或b)。 python需要相当长的时间来检查每个分配的内存位置以查看是否已存在[1,2],将b分配到与a相同的内存位置。
    而且更不用说列表是可变的,即您可以执行以下操作:

    In [46]: a = [1,2]
    
    In [47]: id(a)
    Out[47]: 4421968008
    
    In [48]: a.append(3)
    
    In [49]: a
    Out[49]: [1, 2, 3]
    
    In [50]: id(a)
    Out[50]: 4421968008
    

    看到了吗? a保持的值已更改,但内存位置未更改。现在,如果将一堆其他变量名分配给同一个内存位置怎么办?!它们也会被改变,这将是语言的一个缺陷。为了解决这个问题,python必须将整个列表复制到一个新的内存位置,因为我想更改a的值

    即使是空列表也是如此:

    In [51]: a = []
    
    In [52]: b = []
    
    In [53]: a is b
    Out[53]: False
    
    In [54]: id(a) == id(b)
    Out[54]: False
    

    现在,让我们谈谈我所说的有关指针的内容:

    让我们假设你想要两个变量来实际谈论相同的内存位置。然后,您可以将第二个变量分配给第一个变量:

    In [55]: a = [1,2,3,4]
    
    In [56]: b = a
    
    In [57]: id(a) == id(b)
    Out[57]: True
    
    In [58]: a is b
    Out[58]: True
    
    In [59]: a[0]
    Out[59]: 1
    
    In [60]: b[0]
    Out[60]: 1
    
    In [61]: a
    Out[61]: [1, 2, 3, 4]
    
    In [62]: b
    Out[62]: [1, 2, 3, 4]
    
    In [63]: a.append(5)
    
    In [64]: a
    Out[64]: [1, 2, 3, 4, 5]
    
    In [65]: b
    Out[65]: [1, 2, 3, 4, 5]
    
    In [66]: a is b
    Out[66]: True
    
    In [67]: id(a) == id(b)
    Out[67]: True
    
    In [68]: b.append(6)
    
    In [69]: a
    Out[69]: [1, 2, 3, 4, 5, 6]
    
    In [70]: b
    Out[70]: [1, 2, 3, 4, 5, 6]
    
    In [71]: a is b
    Out[71]: True
    
    In [72]: id(a) == id(b)
    Out[72]: True
    

    看看那里发生了什么! ab都分配到同一个内存位置。因此,您对其中所做的任何更改都将反映在另一个上。

    最后,让我们简单谈谈我之前提到过的窥视孔。 Python试图节省空间。因此,它在启动时会将一些小东西加载到内存中(例如,小整数)。因此,当您将变量分配给一个小整数(如5)时,在将值赋值给内存位置并指定变量名之前,python不必计算5它(与你的清单不同)。因为它已经知道5是什么,并且将它藏在某个内存位置,所以它所做的就是为该内存位置分配一个变量名。但是,对于更大的整数,情况不再是这样:

    In [73]: a = 5
    
    In [74]: b = 5
    
    In [75]: id(a) == id(b)
    Out[75]: True
    
    In [76]: a is b
    Out[76]: True
    
    In [77]: a = 1000000000
    
    In [78]: b = 1000000000
    
    In [79]: id(a) == id(b)
    Out[79]: False
    
    In [80]: a is b
    Out[80]: False
    

答案 1 :(得分:0)

这是python为小整数执行的优化。通常,您不能指望指向同一位置的a和c。如果您尝试使用逐渐变大的整数进行此实验,您会发现它在某个时刻停止工作。我很确定1000足够大但我不在电脑附近;我想我记得从-128到127的所有整数都是以这种方式处理的(或其他一些"整数")。

答案 2 :(得分:0)

您的理解通常是正确的,但值得注意的是,与C或C ++中的数组相比,python列表是完全不同的动物。来自文档:

ID(OBJ) 返回对象的“标识”。这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。具有非重叠生存期的两个对象可能具有相同的id()值。

你的问题的简单答案是python中的列表实际上是引用。这导致它们的内存地址不同,因为地址是引用的地址,而不是人们可能期望的对象。