前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Python中的可变对象和不可变对象

Python中的可变对象和不可变对象

作者头像
py3study
发布于 2020-01-20 04:03:26
发布于 2020-01-20 04:03:26
1.4K00
代码可运行
举报
文章被收录于专栏:python3python3
运行总次数:0
代码可运行

什么是可变/不可变对象

  • 不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。
  • 可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变

Python中,数值类型(intfloat)、字符串str、元组tuple都是不可变类型。而列表list、字典dict、集合set是可变类型。

还是看代码比较直观。先看不可变对象

不可变对象的例子

先说明一点is 就是判断两个对象的id是否相同, 而 == 判断的则是内容是否相同。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a = 2
b = 2
c = a + 0 
c += 0

print(id(a), id(b), id(2))  # id都相同
print(c is b) #True
代码语言:javascript
代码运行次数:0
运行
复制

再来看字符串

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
astr = 'good'
bstr = 'good'
cstr = astr + ''
print(cstr is bstr) # True
print(id(astr), id(bstr), id('good'))  # 三个id相同
代码语言:javascript
代码运行次数:0
运行
复制

和数值类型的结果一样。如果是下面这种情况,变量修改后不在是good

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
astr = 'good'
print(id(astr))
astr += 'aa'
print(id(astr)) # id和上面的不一样
代码语言:javascript
代码运行次数:0
运行
复制

由于是不可变对象,变量对应内存的值不允许被改变。当变量要改变时,实际上是把原来的值复制一份后再改变,开辟一个新的地址,astr再指向这个新的地址(所以前后astr的id不一样),原来astr对应的值因为不再有对象指向它,就会被垃圾回收。这对于int和float类型也是一样的。

再看tuple

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
add = (1, 2, 3)
aee = (1, 2, 3)
print(id(add), id(aee), id((1, 2, 3)))  # id各不相同

aee = (1, 2, 3)
print(id(aee))
aee += () # 加空元组
print(id(aee))  # id变了!
print(aee)  #(123
代码语言:javascript
代码运行次数:0
运行
复制

虽然看上去都是(1 ,2, 3)按理说应该和上面一致才对。难道这是可变对象?再看

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
add = (1, 2, 3)
aee = add 
print(id(aee), id(add)) # 这两个id一样
aee += (4, 5, 6)
print(id(aee)) # aee的id变了!
print(add) # add还是(1, 2, 3)没有变
代码语言:javascript
代码运行次数:0
运行
复制

又和数值类型于str类型一致了。如果是可变对象add = aee,它们指向同一地址(id相同)是肯定的。但不是同一对象的不同引用,因为如果是的话,aee的改变会引起add的改变,再tuple中并不是这样。所以tuple是不可变对象,但又和str和数值类型稍微有点区别。平常说的tuple不可变更多时候是指里面存放的值不能被改变(有些特殊情况,如tuple里面存放了list,可改变list里的元素。但实际上这个tuple并没有被改变)。

对于str、int、float只要在它们再类型相同的情况下,值也相同,那么它们的id相同。(为什么要说类型相同?)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a = 2.0
b = 2
print(a is b)  # False, 一个int一个float,类型都不同
代码语言:javascript
代码运行次数:0
运行
复制

2和2.0就不在一个地址上。

可变对象的例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
lis = [1, 2, 3]
lis2 = [1, 2, 3]
# 虽然它们的内容一样,但是它们指向的是不同的内存地址
print(lis is lis2)
print(id(lis), id(lis2), id([1, 2, 3]))  # 三个id都不同
代码语言:javascript
代码运行次数:0
运行
复制

再看赋值的情况下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
alist = [1, 2, 3]
# alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)
blist = alist
print(id(alist), id(blist))  # id一样
# 所以其中一个变化,会影响到另外一个
blist.append(4)
print(alist)  # 改变blist, alist也变成了[1 ,2 ,3 4]
print(id(alist), id(blist))  # id一样,和上面值没有改变时候的id也一样
代码语言:javascript
代码运行次数:0
运行
复制

blist = alist这一句。alist实际上是对对象的引用,blist = alist即引用的传递,现在两个引用都指向了同一个对象(地址)。所以其中一个变化,会影响到另外一个。

再看看set

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
abb = {1, 2, 3}
acc = abb
print(id(abb), id(acc))
acc.add(4)
print(abb)  # {1, 2, 3, 4} 
print(id(abb), id(acc)) # 相等
代码语言:javascript
代码运行次数:0
运行
复制

和上面list的例子一致。

可变对象由于所指对象可以被修改,所以无需复制一份之后再改变,直接原地改变,所以不会开辟新的内存,改变前后id不变。

当然不可变对象就不是这样了, 可以和这个对比一下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
abc = 3
dd = abc
dd = 43
print(abc)  # 3,并不随dd的改变而改变
代码语言:javascript
代码运行次数:0
运行
复制

但是如果是拷贝,就仅仅是将内容拷贝过去,传递的并是不引用。这在想使用列表的值又不想修改原列表的时候特别有用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
blist = alist[:]  # or alist.copy()
print(alist is blist)  # False
blist.append(4)
print(alist)  # 还是[123]没有变化
代码语言:javascript
代码运行次数:0
运行
复制

作为函数参数

作为函数参数,也是一样的,可变类型传递的是引用,不可变类型传递的是内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
test_list = [1, 2, 3, 4]
test_str = 'HAHA'


def change(alist):
    alist.append(5)


def not_change(astr):
    astr.lower()


change(test_list)
not_change(test_str)
print(test_list)  # 改变了原来的值
print(test_str)  # 没有变

当然了,如果不想改变原来列表的值,参数可以传入列变的拷贝。alsit[:]

有趣的例子

再看一个有趣的例子,我们知道list是可以使用+添加一个列表的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a1 = [1, 2, 3]
a2 = a1
print(id(a1), id(a2))
# 实际上是a2指向了新的对象,id已经改变。
# 所以现在a2、a1并不是同一对象的两个引用了,a2变化a1不会改变
a2 = a2 + [4] # 这个等式中,右边的a2还是和a1的id一样的,一旦赋值成功,a2就指向新的对象
print(id(1), id(a2))  # 不等,a2的id变化了
print(a1) # [1, 2, 3]没有变
代码语言:javascript
代码运行次数:0
运行
复制

如果是这样写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a1 = [1, 2, 3]
a2 = a1
print(id(a1), id(a2))
a2 += [4]  # 相当于调用了a2.extend([4]),原地改变并没有新的对象产生
print(id(1), id(a2))  # 相等,a2的id没有变化
print(a1) 
代码语言:javascript
代码运行次数:0
运行
复制

不同的地方在于a2 += [4],这句相当于调用了a2.extend([4])相当于原地改变,并没有新的对象产生。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/03/28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python可变对象和不可变对象
Python中一切皆对象,每个对象都有其唯一的id,对应的类型和值,其中id指的是对象在内存中的位置。根据对象的值是否可修改分为可变对象和不可变对象。其中,
oYabea
2020/09/07
1.1K0
(一)Python基本语法元素
标准类型运算符,主要进行的是值比较、对象身份比较和布尔运算,具体使用在之后介绍,大概的运算符如下所示:
小点点
2022/12/12
9940
(一)Python基本语法元素
Python入门之python可变对象与不可变对象
本文分为如下几个部分 概念 地址问题 作为函数参数 可变参数在类中使用 函数默认参数 类的实现上的差异 概念 可变对象与不可变对象的区别在于对象本身是否可变。 python内置的一些类型中 可变对象:list dict set 不可变对象:tuple string int float bool 举一个例子 # 可变对象 >>> a = [1, 2, 3] >>> a[1] = 4 >>> a [1, 4, 3] # 不可变对象 >>> b = (1, 2, 3) >>> b[1] = 4 Traceback
Jetpropelledsnake21
2018/05/02
8530
可变对象与不可变对象
前阵子我们聊了下函数的参数传递以及变量赋值的一些内容:关于函数参数传递,80%人都错了。
Crossin先生
2018/07/24
9170
可变对象与不可变对象
Python中的可变对象与不可变对象
+=操作符对应__iadd__魔法方法,对于不可变对象,a+=b和a=a+b等价,对于可变对象并不等价,dict和set不支持+=和+操作符。
雪飞鸿
2023/04/19
8210
【python】不可变对象与可变对象 || 运算符 == 与 is 的区别 || 浅拷贝和深拷贝
不可变对象:是指创建后,内容不可修改的对象。我们只能通过重新创建这个对象的方式来实现修改它的内容。
魏言
2025/02/15
1290
Python - 可变和不可变对象
前置知识 在 Python 中,一切皆为对象 Python 中不存在值传递,一切传递的都是对象的引用,也可以认为是传址 有哪些可变对象,哪些不可变对象? 不可变对象:字符串、元组、数字(int、float) 可变对象:数组、字典、集合 不可变对象和可变对象的区别? 可变对象:改变对象内容,对象在内存中的地址不会被改变 不可变对象:改变对象内容,对象在内存中的地址会被改变;如果必须存储一个不同的值,则必须创建新的对象 不可变对象的应用场景 它们在需要常量哈希值的地方起着重要作用,例如作为字典中的键 从内存角度
小菠萝测试笔记
2021/08/06
1.3K0
python可变对象和不可变对象
在Python中,对象按可变属性可以分为可变对象和不可变对象两种。理解这两种对象的差异对于编写高效且易于维护的代码至关重要。本文将介绍Python中的可变对象和不可变对象,以及在使用它们时需要注意的事项。
程序熵
2023/09/25
6950
python可变对象和不可变对象
PHP工程师学Python数据类型
继上篇文章比较了PHP与Python语法之后,这周又学习了Python数据类型,准备从通过这篇文章给自己进行一些总结,也给其他读者一些参考。
汤青松
2019/07/21
6740
Python(二) 序列
常用的序列结构:列表、元组、字符串、字典、range、zip、enumerate 等
赤蓝紫
2023/01/01
1.8K0
Python面试大全-Python基础
输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。
wangmcn
2022/07/25
4960
Python面试大全-Python基础
探索c#之不可变数据类型
不可变对象 不可变(immutable): 即对象一旦被创建初始化后,它们的值就不能被改变,之后的每次改变都会产生一个新对象。 var str="mushroomsir"; str.Substring(0, 6) c#中的string是不可变的,Substring(0, 6)返回的是一个新字符串值,而原字符串在共享域中是不变的。另外一个StringBuilder是可变的,这也是推荐使用StringBuilder的原因。 var age=18; 当存储值18的内存分配给age变量时,它的内存值也是不可以被
蘑菇先生
2018/05/21
1K0
【python】 深拷贝和浅拷贝:copy模块、可变对象和不可变对象、其他拷贝方式
Python赋值操作或函数参数传递传递的永远是对象引用(即内存地址),而不是对象内容。在Python中一切皆对象,对象又分为可变(mutable)和不可变(immutable)两种类型。
会呼吸的Coder
2020/02/17
1.2K0
python 对象引用、可变性 和 垃圾回收
元组的不可变性 其实是指 tuple 数据结构的 物理内容(即保存的引用)不可变,与引用的对象无关
Michael阿明
2021/09/06
3820
检查Python对象
编程环境中的对象很象现实世界中的对象。实际的对象有一定的形状、大小、重量和其它特征。实际的对象还能够对其环境进行响应、与其它对象交互或执行任务。计算机中的对象试图模拟我们身边现实世界中的对象,包括象文档、日程表和业务过程这样的抽象对象。 类似于实际的对象,几个计算机对象可能共享共同的特征,同时保持它们自己相对较小的变异特征。想一想您在书店中看到的书籍。书籍的每个物理副本都可能有污迹、几张破损的书页或唯一的标识号。尽管每本书都是唯一的对象,但都拥有相同标题的每本书都只是原始模板的实例,并保留了原始模板的大
张善友
2018/01/22
1.3K0
Python进阶学习笔记【干货分享】(二)
print(id(a))a = 4print(id(a))# 重新赋值之后,内存地址发生改变
商业新知
2019/06/19
5370
Python进阶学习笔记【干货分享】(二)
干货 | Python进阶系列之学习笔记(二)
目录 对象 字符串 一、对象 (1)什么是对象 在python中一切都是对象,每个对象都有三个属性分别是,(id)身份,就是在内存中的地址,类型(type),是int、字符、字典(dic)、列表(list)等,最后还有值,例如: a = 12 就是用 12 这个类型为整数的,值为 12,在内存空间中创建了一个空间(这个空间会用一个地址来表示,就是 id ),当对象被创建后,如果该对象的值可以被更改,那么就称之为可变对象(mutable),如果值不可更改,就称之为不可变对象(inmutable) (2)不可
磐创AI
2019/06/19
5140
python学习笔记:深浅拷贝的使用和原理
在理解深浅拷贝之前,我们先熟悉下变量对象和数据类型 1.变量和对象 变量-引用-对象(可变对象,不可变对象) 在python中一切都是对象,比如[1,2],'hello world',123,{'k1
用户1679793
2018/04/28
7260
python学习笔记:深浅拷贝的使用和原理
python 深复制和浅复制详解
id(x)函数 id()函数可以查看一个变量在内存中的地址 变量赋值给变量-拷贝引用 对于以下代码 >>> import copy >>> a=[1,2,3] >>> b=a >>> id(a) """ 4382960392 """ >>> id(b) """ 4382960392 """ >>> id(a)==id(b) #赋值后,两者的id相同,为true。 True >>> b[0]=222222 #此时,改变b的第一个值,也会导致a值改变。 >>> print(a,b) [222222,
演化计算与人工智能
2020/08/14
7940
Python的数据类型(二)
大家好,在上一次推送中,我们一起学习了Python数据结构中的整数int、浮点数float以及复数,今天我们一起来学习其他的一些数据类型吧。
陆勤_数据人网
2020/08/18
1.5K0
Python的数据类型(二)
相关推荐
Python可变对象和不可变对象
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验