【问题标题】:Variable assignment and modification with regards to memory addresses关于内存地址的变量分配和修改
【发布时间】:2019-05-13 04:06:38
【问题描述】:

假设我将两个变量赋值给整数:

a = 1
b = 2

现在,我将a 分配给b

a = b

正如所料,a == 2,因为a已经被设置为b的内存地址。

但实际上并没有。如果我这样做了

b += 1

a 仍然等于 2。为什么a 不指向b

【问题讨论】:

  • 没有设置到内存地址。它的值已被设置。它们只是变量,而不是指针。
  • 所以将一个变量分配给另一个变量只是将第一个变量设置为第二个变量的值,仅此而已?情况似乎并非总是如此
  • 对于整数和浮点数,它将值从一个变量复制到另一个变量。对于更复杂的结构——比如列表、字典、类——它会复制引用,你可能会得到预期的结果。您可以使用PythonTutor 将其可视化。
  • 我认为这个链接对你有用。 stackoverflow.com/questions/37535694/…

标签: python variables memory immutability mutable


【解决方案1】:

示例中的行为如下

In [1]: a = 1                                                                                                                                                                     

In [2]: b = 2                                                                                                                                                                     

In [3]: a = b                                                                                                                                                                     

In [4]: b+=1                                                                                                                                                                      

In [5]: b                                                                                                                                                                         
Out[5]: 3

In [6]: a                                                                                                                                                                         
Out[6]: 2

在例子中,当你做a=b时,a和b都指向同一个引用,但是当你b += 1时,b加1的操作为b创建了一个新的整数值3 b 指向那个值,但是 a 仍然指向旧值 2

请注意,尝试使用诸如列表之类的可变类型来执行此操作,因为您例外的情况会发生在整数上

In [1]: a = [1]                                                                                                                                                                   

In [2]: b = [2]                                                                                                                                                                   

In [3]: a = b                                                                                                                                                                     

In [4]: b.append(2)                                                                                                                                                               

In [5]: a                                                                                                                                                                         
Out[5]: [2, 2]

In [6]: b                                                                                                                                                                         
Out[6]: [2, 2]

In [7]: b += [3, 4];                                                                                                                                                                        

In [8]: b
Out[8]: [2, 2, 3, 4]

In [9]: a
Out[9]: [2, 2, 3, 4]

现在这里发生了什么?我们更改了b,但a 也发生了更改,这是因为append 或列表的更新发生在in-place 并且由于a 指向b,两者最终都得到了更新!

+= 运算符会发生什么由类的__iadd__ 方法定义。对于int-s,所有__iXXX__ 方法都返回一个新的int 实例。对于list-s __iadd__(self, other)self.extend(other); return self,所以变量一直指向同一个对象。

因此,即使是整数也可以表现得像一个列表,例如here@imposeren 礼貌

【讨论】:

  • 所有可变和不可变对象的行为是否相同?例如,元组的行为是否像整数而不像列表?
  • 是的,不同的是你不能对一个元组进行操作,就像你对一个整数进行加法操作一样!
  • 值得一提的是,对于不同的运算符,任何对象都可以随心所欲地返回,例如对于+=,它由obj_cls.__iadd__ 确定。碰巧的是,ints 返回了一个新对象。但是可以定义一个自定义的“int-like”类,重载__iadd__ 方法,以便在+= 上更改当前对象并返回相同的对象。
  • 这个解释听起来不错,但并不正确。起初 id 在这里没有用,因为 CPython 解释器使用了将小整数映射到同一个对象的优化。较大的整数 (>256) 的行为会有所不同。同样在这里,对象是否可变也不是重点。重要的是它们的使用方式以及它们被分配而不是被修改。
  • 我之前评论的示例代码显示了如何将“int-like”对象设置为“可变”:gist.github.com/imposeren/5501a54a2ea0785cac57b104df9218c0。 @DeveshKumarSingh 也许您应该在回答中提及这一点
【解决方案2】:

在其他编程语言中,您所说的称为“指针”。
它们有这个名字是因为它们“指向”事物。
a 指向 bb 指向 2,等等。

我画了一些图片来描述你认为会发生什么,以及实际发生了什么。

您预期会发生什么:

实际发生了什么:

【讨论】:

    【解决方案3】:

    python中的变量是引用。很少有引用指向不可变对象(例如字符串、整数等),而列表和集合是可变的。

    Python 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 22:20:52) [MSC v.1916 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    # Consider two variables x & y  with integers 23 and 46. They have immutable references
    # Meaning, if y=x, it doesn't mean y will change whenever x is updated.
    >>> x=23
    >>> print (x)
    23
    >>> y=46
    >>> print (x)
    23
    >>> print (y)
    46
    >>> y=x
    >>> print (x)
    23
    >>> print (y)
    23
    # Let's change the value of x after the assignment
    >>> x=99
    >>> print (x)
    99
    # Since it is immutable, the value wont change.
    >>> print (y)
    23
    #Let's consider the mutable reference scenario. a & b are two lists which have mutable references
    # Meaning, if b=a, it means b will change whenever a is changed
    >>> a = list([11,22,33,87])
    >>> print (a)
    [11, 22, 33, 87]
    >>> b = list([87,53,98,2])
    >>> print (b)
    [87, 53, 98, 2]
    >>> a=b
    >>> print (a)
    [87, 53, 98, 2]
    >>> print (b)
    [87, 53, 98, 2]
    # Popping the list would alter b
    >>> b.pop()
    2
    >>> print (b)
    [87, 53, 98]
    # Notice the change in value of a
    >>> print (a)
    [87, 53, 98]
    >>>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-17
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      • 2013-08-29
      相关资源
      最近更新 更多