python字符串常量池_Python学习——深入理解python变量

Python学习——深入理解python变量

starry • 2020 年 04 月 09 日

1. 变量&赋值

Python中的变量不同于java、C语言中,后者的变量一旦创建就要说明号变量类型,不可改变;前者则不同,变量随着所赋值的类型改变而改变,原因是在于Python解释器比较高级,在编译的时候先查看所赋值类型再确定变量类型。

1.1 赋值

因此,Python变量其实是一个标签,不占内存,赋值操作完成以下两件事:为所赋的值开辟空间,确定一个唯一的id

将变量作为标签,和这个id绑定(也可以认为指向这个id)

1.2 辨析id()、is 、==id()是求常量的地址标识,一般print(A)打印的是id对应的内存内容,只有用id(A)才能求A指向的id

A is B就是比较A和B对应的id是否一致,返回值为True或False,A或B可以用常量代替

== 则是比较id对应的实际内容是否一致

1.3 B = A

实际上就是将变量A对应的id和B绑定

1.4 重新赋值

相当于重新开辟一个新空间,设置id后,将变量与此id绑定,但是注意1.2中B绑定的id原来的那个,因为B绑定的是id而不是A本身,A没有实际内存,无法指向。m = 1

s = l

m = 2

print(m is s) # False

2. 常量池

和Java类似,Python也有常量池,但是不同的是Python是小整数常量池和字符串常量池。常量池是为了节约空间,相同的内容不用重复开辟空间,在第一次被赋值的时候开辟

python只有小整数[-5, 256]才有常量池,字符串需要满足:仅仅包括下划线、数字、字母,且不能超过20个字符

常量池的存在导致一旦小整数或者字符串在常量池中建立,那么在整个程序中,给不同变量赋相同的小整数或字符串,那么它们对应的id相同,即此小整数id。非常量池的值被赋值时会重复赋值\# 非pycharm等高级IDE

m = 256

n = 256

print(m is n) #True

m = 257

n = 257

print(m is n) #False

PS. 这里有个大坑,就是其实常量池的范围还要视编译器而已,在IDLE范围见上,但是pycharm、VScode较高级的IED中,大整数和较长、带有特殊字符的字符串都是有常量池的\# pycharm等高级IDE

m = 256

n = 256

print(m is n) #True

m = 257

n = 257

print(m is n) #True

3. 浅复制和深复制

浅复制即顶层复制,只复制原结构的最高层内容,有id的部分不会继续复制下去;深复制为递归复制,只要有id就一直寻找到最终内容,将原结构完全复制下来。

举个例子:A = [1,[2,3],4]

B = A[:] # 对A浅复制

A[1][1] = -3

A[0] = -1

print(A) # [-1, [2, -3], 4]

print(B) # [1, [2, -3], 4]

可以认为A、B是二维数组,也就是A[1]和B[1]存的是id/地址,浅赋值只把A[1]也就是[2,3]的id给了B[1],[2, 3]在内存中有自己的空间,对A1操作就会改变B1,print的作用是将所有数组的内容展现出来,虽然B指向内容本身没改变,因为B指向重新开辟的空间,但是print结果会变。以下是深复制,[2,3]也重新开辟了空间:import copy

A = [1,[2,3],4]

B = copy.deepcopy(A)

A[1][1] = -3

A[0] = -1

print(A) # [-1, [2, -3], 4]

print(B) # [1, [2, 3], 4]浅复制有:没有限制条件的分片表达式(L[:])、字典 copy 方法、有些内置函数,例如 list,能够生成拷贝 list(L)

深复制有:copy标准库模块能够生成完整拷贝——deepcopy

4. 可变量

python中的可变量为list类型,即赋值后可以修改;整数、浮点、tuple等为不可变量,一旦赋值,不能修改,当然如果像tuple中内嵌了list,虽然list内容可修改,但是tuple内容本身没变,毕竟只存了list的id。

以下重点讨论字典类型中的key值不能说可变类型的原因:

python字典使用了hash表的数据结构实现,可以将查询更新表的时间代价由O(n)降到O(1):系统先初始化一个固定k个空间大小的hash表H;

建立词典时,先计算h = hash(key), 如果H[h%k]为空,则在此处存放key和value;

如果不为空,则公开寻址,常用的是线性寻址,即往(h+1)%k的方向寻找,直到找到为空的位置;

当表空间不够时,会自动扩容,即增大k,不过前面的位置要重新计算再插入;

表建立后,查询、更新则是先利用hash函数计算key对应的hash值,再求位置,计算法同上,直至找到,如果遍历完找不到则会报错。

假设key值不固定,即为list类型,计算hash值时,如果是基于内容计算(如tuple就是),由于list内容可变,那么当内容变化了,则key值对应的索引通常也会变化(hash性质);如果是基于id,则由于list类型并非存于常量池(见下代码),所以建表的list的id和查询的id不一致,key值不一致就无法对应。print([1,2] is [1,2]) #False

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值