一. id, is 与 ==
1 name = "ad" 2 3 print(id(name)) 4 # 2738647174536 5 6 # is —— 比较两边的内存地址是否相等 7 # == —— 比较两边的数值是否相等 8 i1 = 1000 9 i2 = 1000 10 print(i1 is i2)
11 12 # 如果是在终端内一步一步输入上面的内容,则相当于 i1 与 i2 是两个代码块,结果就是 False 13 # 反之像现在这样在同一个代码块里的话,结果就是 True 14 # 这里所说的代码块可以理解为一个文件就是一个代码块 15 16 # 在终端里一行 ">>>" 代表一个代码块 17 print(i1 == i2) # True 18 19 # 如果内存地址相同,值一定相同,反之则不一定。
二. 代码块
1. 作为一个单元执行
一个模块,一个函数,一个类都是一个代码块
2. 代码块的缓存机制:
2.1 Python在执行同一个代码块的初始化对象(也就是设置变量)的命令时,会检查是否其值是否已经存在。如果存在,会将其重用。
2.2 也就是说,遇到初始化对象的命令时,会将初始化的这个变量与值存储在一个字典中,
2.3 在遇到新的变量时,会先在字典中查询,如果有同样的记录,那么它会重复使用这个字典中之前的这个值。比如:
1 i1 = 100 2 i2 = 100 3 4 print(id(i1)) # 1407285088 5 print(id(i2)) # 1407285088 6 7 # 注意与上面 i1 = 1000 那个例子比较看结果 8 # 程序执行时会把 i1、i2 两个变量指向同一个对象 9 # 如果满足缓存机制则它们在内存中只存在一个,即它们的 id 相同。 10 # 注意这里重点是在同一个代码块下! 11 12 a = [1, 2, 3] 13 b = [1, 2, 3] 14 print(a is b) # False
代码块的缓存机制适用范围:
int(float)
str
bool
int(float) —— 任何数字在同一个代码块中都会复用
bool —— True 和 False 在字典中会以1, 0方式存在,并且复用
str —— 几乎所有的字符串都会符合缓存机制
以上内容表明代码块的缓存机制的优点:
a. 节省内存
b. 提升性能
3. 非乘法得到的字符串都满足代码块的缓存机制。
1 s1 = "as12$%#$" 2 s2 = "as12$%#$" 3 4 print(s1 is s2) # True 5 6 注意这里是在同一个代码块里 7 如果在终端内运行的话相当于在不同代码块里,结果就变了
1 4 乘法得到的字符串分两种情况: 2 3 4.1 乘数为1时,任何字符串满足代码块的缓存机制: 4 5 b1 = '太白@5847395QQ0743895*&^%$#((&_+(())' * 1 6 a1 = '太白@5847395QQ0743895*&^%$#((&_+(())' * 1 7 8 print(a1 is b1) # True 9 10 4.2 乘数 >= 2时:仅含大小写字母,数字,下划线,总长度 <= 20,满足代码块的缓存机制: 11 12 s1 = 'old_' * 5 13 s2 = 'old_' * 5 14 print(s1 is s2) # True 15 16 优点: 17 能够提高一些字符串,整数处理人物在时间和空间上的性能; 18 需要值相同的字符串,整数的时候,直接从‘字典’中取出复用,避免频繁的创建和销毁,提升效率,节约内存。
三,小数据池
1. 小数据池,也称为小整数缓存机制,或者称为驻留机制等等。
大前提:小数据池也是只针对
int(float),str,bool。
2. 注意,小数据池是针对不同代码块之间的缓存机制
3. Python自动将 -5~256 的整数进行了缓存。
当将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。
4. python会将一定规则的字符串在字符串驻留池中,创建一份
当将这些字符串赋值给变量时,并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象。
5. 其实,无论是缓存还是字符串驻留池,都是python做的一个优
就是将 -5-256 的整数,和一定规则的字符串,放在一个‘池’(容器,或者字典)中
无论程序中那些变量指向这些范围内的整数或者字符串,那么直接在这个‘池’中引用,即在内存中之创建一个。
5.1 优点:
1) 能够提高一些字符串,整数处理人物在时间和空间上的性能;
2) 需要值相同的字符串,整数的时候,直接从‘池’里拿来用,避免频繁的创建和销毁,提升效率,节约内存。
6. int:那么大家都知道对于整数来说,小数据池的范围是 - 5
~256 ,如果多个变量都是指向同一个(在这个范围内的)数字,他们在内存中指向的都是一个内存地址。
str: 字符串要从下面这几个大方向讨论(了解即可!):
1, 字符串的长度为0或者1,默认都采用了驻留机制(小数据池)。
2, 字符串的长度 > 1, 且只含有大小写字母,数字,下划线时,才会默认驻留。
四,小结。
如果在同一代码块下,则采用同一代码块下的缓存机制。
如果是不同代码块,则采用小数据池的驻留机制。
编码:
1. 之前讲过 ASCII、Unicode、UTF-8、GBK这四种编码。
2. 不同的编码之间不能互相识别(报错或出现乱码),不能相互转化
3. 国际通用标准:文字通过网络传输,或者硬盘存储等不能使用Unicode编码方式。
(因为Unicode都是使用升级版32位的,太费流量了)
4. 在 python3x 环境下,唯独 str 类型在内存中的编码方式是 Unicode,
所以字符串不能直接进行网络传输及文件的存储
5. bytes —— 数据类型,不是字节,与 str 类型就像是一对孪生兄弟
1 s1 = "alex" 2 s2 = b"alex" 3 4 print(type(s1)) # <class 'str'> 5 print(type(s2)) # <class 'bytes'>
那么为啥要有 bytes ? —— bytes内部编码非Unicode方式,因此可以进行网络传输和文件的存储
前面提到,str 类型却是 Unicode方式,那为什么不用 bytes 而是用 str?
因为,bytes 中文是16进制。
因此,当需要网络传输数据,文件存储数据时要考虑用 bytes。
英文
str 的表现形式:"alex"
内部编码: Unicode
中文
str 的表现形式: "中文"
内部编码:Unicode
1 # 由以上信息,str 转化成 bytes 的方法是: 2 # unicode --> gbk字符串 --> gbk编码方式的bytes 3 4 s = "中国" # 因为PythOn3x中 str 编码方式就是 Unicode,所以这里等同于 s = u"中国" 5 a = s.encode("gbk") 6 7 print(s, type(s)) # ('中国', <class 'str'>) 8 print(a, type(a)) # (b'xd6xd0xb9xfa', <class 'bytes'>) 9 10 s1 = a.decode("gbk") # 注意这里是 decode 11 print(s1, type(s1)) # ('中国', <class 'str'>) 12 # 在上面 4-11 行的代码中,首先 s = "中国" 是以 Unicode编码方式的 str
13 # 然后 a = s.encode("gbk") 是将 Unicode 编码方式的 str 转化成 以 gbk 编码方式的 bytes
14 # 最后是 s1 = a.decode("gbk") 则将 gbk 编码方式的 bytes 转化成 以 Unicode 编码方式的 str
15
16 # encode 编码 17 # decode 解码 18 19 # unicode --> utf-8 字符串 --> utf-8 编码方式的bytes 20 21 s2 = "语言" 22 b = s2.encode("utf-8") 23 print(b, type(b)) # (b'xe8xafxadxe8xa8x80', <class 'bytes'>) 24 s3 = b.decode("utf-8") 25 print(s3, type(s3)) # ('语言', <class 'str'>)
前面提到不同的编码之间不能互相识别(报错或出现乱码),不能相互转化。
因此它们要通过 Unicode 编码方式来相互转化。