Python中的冷知识
可变对象与不可变对象
为了理解对象的可变与不可变, 首先理解什么是变量
, 什么是对象
在 Python 中,变量
都是指针;指针的内存空间与数据类型无关,其内存空间保存了指向数据的内存地址。
在 Python 中,一切皆对象
,其主要由以下部分组成:
- identity(ID):标识对象的“内存地址”,可使用 id(obj) 获取(唯一标识)
- type(类型):标识对象的“类型”,可使用 type(obj) 获取
- value(值):标识对象的“值”,可使用 print(obj) 获取
注意: 对象的本质是一个内存块
注意: 变量无类型,对象有类型;变量位于栈内存,对象位于堆内存。
变量指向一个对象, 可变不可变指的是变量指向的对象是否可变, 在程序中的表现就是, 不可变对象修改变量值时由于其对象不可变,那么需重新开辟内存空间储存新值后在赋予给变量, 而可变对象修改变量时,是直接在原来内存中修改的.
不可变对象
定义: 不可变对象是指,一个对象所指向的地址上值是不能修改的. 如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了
不可变对象包括:bool(布尔)、int(整数)、float(浮点数)、str(字符串)、tuple(元组)、frozenset(不可变集合),具有以下特性:
- 可hash(不可变长度)
- 不支持新增/删除/修改
- 支持查询
可变对象
定义: 可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值
可变对象包括:list(列表)、set(集合)、dict(字典),具有以下特性:
- 不可 hash(可变长度)
- 支持新增/删除/修改/查询
所以, 可变对象与不可变对象的区别就是, 改变其值后使用id()查看内存地址是否改变
Python参数是值传递还是引用传递
在 Python 参数传递中,不存在所谓值传递和引用传递的区分,其本质都是拷贝对象的引用(指针)传递。
def func1(a):
print(id(a))
a = 654321
print(id(a))
b = 123456
print(id(b))
func1(b)
# 1921163820176
# 1921163820176
# 1921163819760
def func2(a):
print(id(a))
a.append(2)
print(id(a))
c = [1]
print(id(c))
func2(c)
# 1921163742528
# 1921163742528
# 1921163742528
从以上来看, 在Python中不管是可变对象还是不可变对象, 在传递参数时都是引用传递
. 区别是传递给函数后, 改变其值后, 可变对象的地址不变, 而不可变对象的地址改变. 这也是为什么说 Python里所有的数据类型都是对象(python中一切皆为对象
)
这里需和其他编程语言做个区别, 其他编程语言是分为值传递和引用传递的. 值传递是将其值复制一份传给函数, 其内存地址是改变的.
Python中小整数声明时值相同时地址也相同
Python中对于小的整数存在一个缓存池。为了避免因创建相同的值而重复申请内存空间所带来的效率问题, Python解释器会在启动时创建出小整数池,范围是[-5,256]
,该范围内的小整数对象是全局解释器范围内被重复使用,永远不会被垃圾回收机制回收。
>>> a = 1
>>> b = 2
>>> id(a)
2708248357168
>>> id(b)
2708248357200
>>> a = a+1
>>> id(a)
2708248357200
>>> m = 123456789
>>> n = 123456789
>>> m is n
False
>>> id(m)
2004539308784
>>> id(n)
2004539309200
在函数内操作函数外的变量
a = 1
def change():
x = 10 + a
print(x)
change() # 正常打印出11
print(a)
a = 1
def change():
a = 10 + a
print(a)
change() # UnboundLocalError: local variable 'a' referenced before assignment
print(a)
注意: 如果我们想 在函数中修改函数外变量 就会出现问题
, 这是因为,a = 10 + a是一条赋值语句
,Python解释器会将 a 认作局部变量
,所以 10 + a 因为 a 这个局部变量还没有定义,而抛出这样的错误。
知识点: 当在函数中调用未被定义的变量时, 先会在local局部变量中搜索该变量名, 如果找不到会向上搜索, 再查不到就在global中搜索.
最后更新于 2023-02-10 18:21:23 并被添加「」标签,已有 477 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭