Python – 对象的性质:可变与不可变

摘要

Python中,一切都是目标。传递的不是值,而是目标的引用,有点像传址。有些目标不能改变,比如字符串、数组和数字。有些目标是可变的,比如二维数组、字典和集合。可变目标可以改变内容,但地址不变。不能变目标改变内容会改变地址。

正文

外置专业知识

  • 在 Python 中,一切皆为目标
  • Python 中不会有值传送,一切传送的全是目标的引入,还可以觉得是传址

 

有什么可变性目标,什么不能变目标?

  • 不能变目标:字符串数组、元组、数据(int、float)
  • 可变性目标:二维数组、词典、结合

 

不能变目标和可变性目标的差别?

  • 可变性目标:更改目标內容,目标在运行内存中的详细地址不容易被更改
  • 不能变目标:更改目标內容,目标在运行内存中的详细地址被更改

 

从运行内存视角考虑说下有什么不同?

不能变目标

  • Python 中的自变量有一个存储空间
  • 实际的数据信息(目标)也有一个存储空间
  • 而自变量储存(偏向)的是储存数据信息(目标)的基址,一般也叫目标引入
  • 不能变目标就是指目标內容自身不能变
  • 变的是:更改了值,会建立新目标,随后自变量更改了目标引入,偏向了新目标,旧目标会被垃圾分类回收

 

可变性目标

变的是:原先目标的內容,不容易建立新目标,而自变量也或是偏向原目标

 

从编码视角看一下差别 

不能变目标-整形

a = 123
b = a
print(id(a))
print(id(b))
print(a, b)

a  = 2

print(id(a))
print(id(b))
print(a, b)


# 輸出結果
4473956912
4473956912
123 123
4473956976
4473956912
125 123
  • 过去2次打印出能够见到,a、b 自变量储存的基址是同一个,她们们都储存了 123 的基址(123 目标的引入)
  • 预估状况:在 a 干了加减法取值计算以后,即然她们一开始全是偏向同一个基址,按大道理改动 123 后,她们也应当依然偏向同一个基址呀,可是并沒有!
  • 具体情况:a 偏向了新的基址,而 b 依然偏向旧的基址,因此 她们的值也不一样

 

能够看一下下边的图

最先,这是一个运行内存地区

基本原理

  • 由于数据(int、float) 是不能变目标,因此 不可以在 123 的基址上立即改动数据信息
  • 加减法取值,事实上是将原先的 123 拷贝了一份到新的基址,随后再做加减法,获得一个新的值 125,最终 a 再偏向新的基址

 

不能变目标-字符串数组

a = "test"
b = a
print(id(a))
print(id(b))
print(a, b)

a  = "123"

print(id(a))
print(id(b))
print(a, b)


# 輸出結果
4455345392
4455345392
test test
4455818288
4455345392
test123 test

 

不能变目标-元组

a = (1, 2, 3)
b = a
print(id(a))
print(id(b))
print(a, b)

a = a   a
print(id(a))
print(id(b))
print(a, b)


# 輸出結果
4455410240
4455410240
(1, 2, 3) (1, 2, 3)
4455359200
4455410240
(1, 2, 3, 1, 2, 3) (1, 2, 3)

  

可变性目标目录

# 目录
a = [1, 2, 3]
b = a

print(id(a))
print(id(b))
print(a, b)

a  = [4, 5, 6]

print(a, b)
print(id(a))
print(id(b))


# 輸出結果
4327665856
4327665856
[1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6]
4327665856
4327665856

能见到 a 自变量改动值以后,b 的值也随着改动了

 

能够看一下下边的图

 

  • 由于 list 是不能变目标,因此 并不会将原先的值拷贝到新的基址再更改,只是立即在原先的基址上改动数据信息
  • 由于 a、b 全是偏向原先的基址的,因此 a、b 自变量储存的基址是一致的(目标引入是一致的),自然值也是一样的啦

 

Python 涵数的参数传递

这儿先提早讲讲涵数的新手入门,由于参数传递是个挺关键的点

 

定义

  • 开始有讲到,Python 的一切传送全是目标的引入,涵数参数传递都不除外
  • 当传送给涵数的是一个自变量,事实上传送的是自变量储存的目标引入(自变量偏向的基址)
  • 在涵数內部改动自变量时,会依据自变量偏向的基址,去改动相匹配的值才对,客观事实简直这般吗

 

参数传递不能变目标

# 涵数
def test_no_define(age, name):
    age = 123
    name = "poloyy"
    print(age, name)


age = 1
name = "yy"
print(age, name)

test_no_define(age, name)
print(age, name)


# 輸出結果
1 yy
123 poloyy
1 yy

 

 

参数传递可变性目标

# 涵数
def test_define(dicts, sets):
    dicts['age'] = 24
    sets.pop()
    print(dicts, sets)


dicts = {"age": 123}
sets = {1, 2}
print(dicts, sets)

test_define(dicts, sets)
print(dicts, sets)


# 輸出結果
1 yy
{'age': 123} {1, 2}
{'age': 24} {2}
{'age': 24} {2}

  

汇总

  • 当涵数参数传递的自变量是不能变目标的情况下,涵数内更改变量类型,涵数外的自变量不容易随着更改
  • 当涵数参数传递的自变量是可变性目标的情况下,涵数内更改变量类型,涵数外的自变量随着更改

 

关注不迷路

扫码下方二维码,关注宇凡盒子公众号,免费获取最新技术内幕!

温馨提示:如果您访问和下载本站资源,表示您已同意只将下载文件用于研究、学习而非其他用途。
文章版权声明 1、本网站名称:宇凡盒子
2、本站文章未经许可,禁止转载!
3、如果文章内容介绍中无特别注明,本网站压缩包解压需要密码统一是:yufanbox.com
4、本站仅供资源信息交流学习,不保证资源的可用及完整性,不提供安装使用及技术服务。点此了解
5、如果您发现本站分享的资源侵犯了您的权益,请及时通知我们,我们会在接到通知后及时处理!提交入口
0

评论0

请先

站点公告

🚀 【宇凡盒子】全网资源库转储中心

👉 注册即送VIP权限👈

👻 全站资源免费下载✅,欢迎注册!

记得 【收藏】+【关注】 谢谢!~~~

立即注册
没有账号?注册  忘记密码?

社交账号快速登录