【问题标题】:Are aliases guaranteed to refer to the same object in Python?别名是否保证在 Python 中引用相同的对象?
【发布时间】:2014-10-08 12:13:13
【问题描述】:

Python docs 提到以下关于名称是对象的别名:

对象具有个体性,多个名称(在多个范围内)可以绑定到同一个对象。这在其他语言中称为别名。乍一看 Python 通常不会意识到这一点,在处理不可变的基本类型(数字、字符串、元组)时可以安全地忽略它。然而,别名对涉及可变对象(如列表、字典和大多数其他类型)的 Python 代码的语义可能产生令人惊讶的影响。这通常用于程序的好处,因为别名在某些方面表现得像指针。例如,传递一个对象很便宜,因为实现只传递了一个指针;如果一个函数修改了作为参数传递的对象,调用者将看到变化——这消除了对 Pascal 中两种不同的参数传递机制的需要。

在其他一些高级语言中,出于性能原因,原始类型通常是特殊类型的,并且是被复制而不是引用的。例如,在 Java 中:

int a = 20000;
int b = a;

上面的代码将复制值20000,而不是指向值20000 的指针。在这种情况下,ab 可能会占用内存中的不同位置。由于== 上的特殊情况仅用于测试原始类型的相等性而不是身份,但是我不相信这种行为可以在普通代码中进行自省。

另一方面,在 Python 3 中对 intstr 等类型的有限测试表明,确实复制的是指针而不是文档中指定的值:

a = 20000
b = a
a is b # True

这是一个非常好的属性,它使语言非常一致,因为原始类型没有特殊情况。所有分配都将名称重新分配给另一个对象。但是,出于性能原因,Python 解释器是否可以处理特殊情况类型,例如 int

因此,我的问题是:原始类型的此属性是否得到保证?换句话说,无论使用哪种 Python 解释器,在b = a 之后,比较 a is b 是否总是真的是True

【问题讨论】:

  • “保证跨解释器”在 Python 中可能是一件棘手的事情,因为该语言的许多微妙方面都没有明确说明。 (我不确定这是否是其中之一,可能不是。)
  • 名称-对象绑定不是 Python 实现的一个微妙方面,而是该语言的基本原则。
  • "上面的代码将复制值 20000,而不是指向值 20000 的指针。"但两者在语义上没有区别。 “在这种情况下,a 和 b 可能会占据内存中的不同位置。”如果ab 是引用类型Integer 也是如此——变量ab,它们是引用(指针)在内存中占据不同的位置;他们只是指向同一个对象。同样的事情发生在 Python 中。变量ab在内存中占据不同的位置;它们只是指向同一个对象。

标签: python pass-by-reference


【解决方案1】:

b = a 使名称 ba 引用完全相同的对象。所以是的,在 Python 中,a is b 将始终为 True。

【讨论】:

    【解决方案2】:

    是的,在the documentation中指定:

    如果目标是标识符(名称):

    如果名称没有出现在当前代码块中的全局语句中:名称绑定到当前本地命名空间中的对象。

    否则:名称绑定到当前全局命名空间中的对象。

    (在 Python 3 中还有一个与 nonlocal 相关的额外案例,但规则相同;唯一的区别是绑定发生在哪个命名空间中。)

    请注意,至关重要的是,这只适用于分配给裸名的情况。如果作业是 a.foo = ba[blah] = b 之类的,那么所有的赌注都没有了,几乎任何事情都可能发生。

    【讨论】:

      【解决方案3】:
      >>> int
      <class 'int'>
      

      Python 使用原始类型的方式与 Java 不同。正如您在此处看到的,int 是一个类。这个类的实例是objects。碰巧这是一个内置类,而不是在某处的.py 文件中定义的类。

      想想Integerint 的Java 行为。

      当您执行a = 1; b = a 时,您将b 设置为对a 所引用的同一对象的引用,因此它不会复制该值。

      就特殊大小写而言,CPython 确实将“小”整数(从 -5 到 255)制成单例,因此不必重新创建它们,但这是一个实现细节。

      【讨论】:

        【解决方案4】:

        Python 中的所有变量和表达式都是引用(语义上等同于指向对象的指针)。如果你熟悉一个 C++,它是这样的:

        object *a = new object(20000);
        object *b = a;
        a == b // true
        

        将一个变量分配给另一个变量将复制值,一个指针。赋值后两个指针总是指向同一个对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-19
          • 1970-01-01
          • 2019-06-30
          • 1970-01-01
          • 2011-11-11
          • 2021-08-16
          相关资源
          最近更新 更多