【问题标题】:Python referencesPython 参考资料
【发布时间】:2011-02-17 08:01:29
【问题描述】:

有人可以解释为什么整数示例导致 x 和 y 的值不同,而列表示例导致 x 和 y 是同一个对象吗?

x = 42
y = x
x = x + 1
print x # 43
print y # 42

x = [ 1, 2, 3 ]
y = x
x[0] = 4
print x # [4, 2, 3]
print y # [4, 2, 3]
x is y # True

【问题讨论】:

标签: python immutability


【解决方案1】:

正如前面的答案所说,您编写的代码将同一对象分配给不同的名称,例如别名。 如果要将原始列表的副本分配给新变量(实际上是对象) 使用这个解决方案:

>>> x=[1,2,3]
>>> y=x[:] #this makes a new list
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x[0]=4
>>> x
[4, 2, 3]
>>> y
[1, 2, 3]

【讨论】:

    【解决方案2】:

    如果你使用y = x,y 和 x 是对同一个对象的引用。但是整数是不可变的,当您执行x + 1 时,会创建新的整数:

    >>> x = 1
    >>> id(x)
    135720760
    >>> x += 1
    >>> id(x)
    135720748
    >>> x -= 1
    >>> id(x)
    135720760
    

    当你有一个可变对象(例如列表、你自己定义的类)时,只要 y 改变,x 就会改变,因为它们指向单个对象。

    【讨论】:

      【解决方案3】:
      【解决方案4】:

      因为整数是不可变的,而列表是可变的。从语法中可以看出。在x = x + 1 中,您实际上是在为x 分配一个新值(它在LHS 上是单独的)。在x[0] = 4 中,您调用列表中的索引运算符并给它一个参数 - 它实际上等同于x.__setitem__(0, 4),这显然是在更改原始对象,而不是创建新对象。

      【讨论】:

      • 不能获取不可变对象的引用吗?
      • 所有“变量”都是引用。区别在于您不能更改不可变对象。一旦它们被创建,它们就永远不会改变 - 任何尝试的更改都会创建一个新对象。
      • 声明“为 x 分配一个新值”是虚伪的,并且可能令人困惑。正在发生的事情是对新对象的引用(x + 1 的结果)绑定到名称 x。 Python 没有左值/右值的概念,因为所有内容都被引用 - 所以区别很重要。
      • @Jeremy Brown:我坚持我的措辞。新值是通过计算表达式 x + 1 创建的对象。在赋值之后(这就是它在 Python 文档中的名称)x 指的是新值。 Python中有一个右值/左值的概念。它与其他语言不同,但它就在那里——这就是为什么= 的左侧在基本赋值语句中必须是一个(通常是单数)标识符序列,而不是一个表达式。见:docs.python.org/reference/…
      • 注意第一句的措辞(强调我的)——“赋值语句用于(re)bind名称到值......”右值/左值非常具体对类 C 语言的意义(这不是一般的 BNF 概念)。您的措辞暗示有一个分配了值的内存“插槽”。在 Python 中情况并非如此,这就是为什么不能重载赋值运算符的原因。我只是建议使用诸如绑定/重新绑定之类的术语来完全消除分配的工作方式。我看到的新 Python 程序员最常见的陷阱是不理解这个参考概念。
      【解决方案5】:

      那是因为当你在 python 中有一个列表或元组时,你会创建一个对对象的引用。 当您说 y = x 时,您使用 y 引用与 x 相同的对象。 所以当你编辑 x y 的对象时会随之改变。

      【讨论】:

      • “当你有一个列表或一个元组时”非常具有误导性。
      • 是的,我很抱歉。我的意思是,两者中的哪一个无关紧要,因为它们都是不可变的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多