Python docs提到以下关于名称是对象的别名:
对象具有个性,多个名称(在多个范围内)可以绑定到同一个对象。这在其他语言中称为别名。乍一看Python时通常不会理解这一点,在处理不可变的基本类型(数字,字符串,元组)时可以安全地忽略它。但是,别名对包含可变对象(如列表,字典和大多数其他类型)的Python代码的语义可能会产生惊人的影响。这通常用于程序的好处,因为别名在某些方面表现得像指针。例如,传递一个对象很便宜,因为实现只传递一个指针;如果函数修改了作为参数传递的对象,调用者将看到更改 - 这消除了对Pascal中两个不同的参数传递机制的需要。
在其他一些高级语言中,由于性能原因,原始类型通常是特殊的,并且被复制而不是引用。例如,在Java中:
int a = 20000;
int b = a;
上面的代码将复制值20000
,而不是指向值20000
的指针。在这种情况下,a
和b
可能会占用内存中的不同位置。由于==
上的特殊外壳仅测试基本类型的相等而不是标识,我不相信这种行为可以在普通代码中被反省。
另一方面,在Python 3中使用int
和str
等类型进行的有限测试表明,实际上,指针是复制的而不是值,如文档中所指定的那样:
a = 20000
b = a
a is b # True
这是一个非常好的属性,使语言非常一致,因为原始类型没有特殊的外壳。所有分配都将名称重新分配给另一个对象。但是,出于性能原因,Python解释器是否可能使用像int
这样的特殊情况类型?
因此,我的问题是:原始类型的这个属性是否得到保证?换句话说,在b = a
之后,无论使用Python解释器,比较a is b
都是True
,总是如此吗?
答案 0 :(得分:4)
b = a
使名称b
和a
引用完全相同的对象。所以是的,在Python中,a is b
将始终为True。
答案 1 :(得分:3)
是的,它在the documentation中指定:
如果目标是标识符(名称):
如果名称未出现在当前代码块的全局语句中:名称绑定到当前本地名称空间中的对象。
否则:名称绑定到当前全局命名空间中的对象。
(在Python 3中还有一个与nonlocal
相关的附加案例,但规则是相同的;唯一的区别是绑定发生在什么命名空间。)
注意,至关重要的是,这仅适用于指定裸名的情况。如果作业类似于a.foo = b
或a[blah] = b
,则所有投注均已关闭,几乎任何事情都可能发生。
答案 2 :(得分:2)
>>> int
<class 'int'>
Python不像Java一样使用原始类型。如您所见,int
是一个类。这个类的实例是 objects ,具有所有这些意义。碰巧这是一个内置类而不是某个.py
文件中定义的类。
考虑Integer
vs int
的Java行为。
执行a = 1; b = a
时,您将b
设置为对a
引用的同一对象的引用,因此它不会复制该值。
就特殊外壳而言,CPython确实能够制造出小型的外壳。整数(从-5到255)变成单例,因此不必重新创建它们,但这是一个实现细节。
答案 3 :(得分:0)
Python中的所有变量和表达式都是引用(在语义上等同于指向对象的指针)。如果您熟悉C ++,则如下所示:
object *a = new object(20000);
object *b = a;
a == b // true
将一个变量分配给另一个变量将复制该值,即指针。在赋值之后,两个指针将始终指向同一个对象。