python对象的引用特征和可变性

本文探讨Python中对象的身份(is)与相等性(==)的区别,通过实例讲解别名与新对象的概念,并解析元组中可变对象的变化特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对象的身份,相等性和别名

先看一个例子:

>>> a = [1,2,3,4]
>>> b = a
>>> b is a
True
>>> id(a),id(b)
(58065824, 58065824)
>>> a.append(5)
>>> a
[1, 2, 3, 4, 5]
>>> b
[1, 2, 3, 4, 5]
>>> 

(1)这里的b就是a的一个别名(alias)

(2)所以is返回true,id()函数对a和b返回的值也是相同的

(3)针对a的修改也同时修改了b

继续:

>>> c = [1,2,3,4,5]
>>> c == a
True
>>> c is a
False
>>> 

(1)这里的c的值与a相等,所以==返回True

(2)但是c不是a的别名,它们的id不同

它们在内存中的数据模型如下图所示:

这里写图片描述

为什么会有上面的不同呢?

其实,在python手册中的数据模型解释中有这么一段话:

Every object has an identity, a type and a value. An object’s identity never changes once
it has been created; you may think of it as the object’s address in memory. The is operator
compares the identity of two objects; the id() function returns an integer representing its identity.

主要意思:

(1) 每个对象都有一个唯一的id,(CPython中id就是对象在内存中的地址),且在创建的时候确定,以后不再改变;

(2) is比较是比较两个对象的id;

(3) id()函数返回的是一个整形的对象id;

上面的例子中c是一个新创建的对象,虽然内容和a一样,但是id是不同的,所以is返回的是False,而b仅仅是a的一个别名,相当于C++中的引用,b和a在内存中的地址是一样的,是同一个对象,所以is返回True。至于c和a的==比较返回True,下面会继续解释。

何时选择is,何时用==

==操作符比较的是对象的内容,而is比较的是对象的id。

==操作符在比较的时候其实是调用了对象的.eq()函数, a == b其实是调用了a.eq(b)的结果。这也就是为什么is会比==快的原因。

元组(tuple) 不变性的一个陷阱

元组(tuple)和其他容器类型一样,存放的都是对象的引用,元组是不可改变的,但是如果它的元素是可变类型的,那么它还是可以被改变的。下面的例子可以说明:

>>> t1= (1,2,[3,4])
>>> t1[-1].append(5)
>>> t1
(1, 2, [3, 4, 5])
>>>

通过Python Online Tutor可以看到这里的内存数据结构如下图:

这里写图片描述

这里写图片描述

在看如下操作,
t1[2] += [6,7]
这个会发生什么呢?

>>> t1[2] += [6,7]
Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    t1[2] += [6,7]
TypeError: 'tuple' object does not support item assignment
>>> t1
(1, 2, [3, 4, 5, 6, 7])

可以看到,抛出了异常,这很好理解,tuple是不可变的,针对tuple元素的赋值会抛出TypeError异常。但是这里的t1中的列表元素还是变了,再看下执行前后的状态。

这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值