一些情况下,先后创建两个变量,两个变量的值相同,会分别开辟一个内存空间放变量对应的值,这个时候变量的值相等,但是内存空间地址是不一样的
但是创建内存空间是需要时间的,对于经常使用的数如果每次使用都要开辟新的内存空间就会浪费空间,影响效率,所以引入小整数池的概念。
小整数池
>>> a =1000
>>> b =1000
>>> print(id(a))
1787434018576
>>> print(id(b))
1787434018448
>>> c = 58
>>> d = 58
>>> print(id(c))
140727893723184
>>> print(id(d))
140727893723184
开辟内存空间是需要时间的,在运行代码的时候会先去创建一个内存地址,去装这个值,然后把内容地址指向变量,最终把这个值赋值给变量。
但是 对于那些我们经常使用到的值,如果我们每次使用的时候都去创建一个新的内存地址去保存,就会浪费空间,影响效率。
所以,引入python中一个小整数池的概念(有利于节省空间,提高效率)
它会把 -5到256这些常用的数字存在固定的地方,不管创建多少个区间里的数字,相同的数字永远都是指向同一个内存地址。
字符串的内存驻留机制(大整数池)
字符串的内存驻留机制(引用计数机制)
字符串驻留是一种在内存中仅保存一份相同且不可变字符串的方法
对于短字符串,将其赋值给多个不同的对象时,内存中只有一个副本,长字符串不遵守驻留机制。(python中的引用计数机制,并不是对所有的数字、字符串,它只对’[0-9],[A-Z],[a-z]和下划线有效,当字符串中有其他的字符比如:! @ % - # ¥时,字符串驻留机制是不起作用的。
驻留适用范围:
- 字符串长度为0或1时,默认驻留
- 字符串长度大于1时,且字符串中只包含大小写字母,数字,下划线时,采用驻留机制。
- 对于[-5,256]之间的整数数字,python默认驻留
- 字符串只在编译时进行驻留,而非运行时,,python是解释型语言,但是事实上,它的解释器也可以理解是一种编译器,它负责将python代码翻译成字节码,也就是.pyc文件。
- 用乘法得到的字符串,如果长度<20且字符串中只包含数字,大小写字符,下划线时,支持驻留,长度>20不支持驻留,这样设计的目的是为了保护.pcy文件不会被错误代码搞得过大。
例1:
>>> str1 ='sten_waves'
>>> str2 ='sten_waves'
>>> str1 is str2
True
>>> id(str1)
2256464209136
>>> id(str2)
2256464209136
>>>
例2: 带空格字符
>>> str3 = 'wten waves'
>>> str4 ='sten waves'
>>> str3 is str4
False
>>> id(str3)
1596460590192
>>> id(str4)
1596460603696
>>>
从例1和例2可以看出非字母,数字,字符串,下划线组成的字符串不会触发驻留机制
python中的驻留机制发生在compile time(编译),而不是run_time
>>> str1='sten'+'waves' # compile_time
>>> str1 is 'stenwaves'
True
>>> str3='sten'
>>> str4=str3+'waves'
>>> str4 is 'stenwaves' # run_time
False
优缺点
- python标识符的不可变性导致了字符串的改动不是采用replace,而是重新创建对象。为了节省内存,涉及字符串的改动通常通常用join()而非+,因为+会多次创建对象,而join()只创建一次对象
- 驻留机制会提升一些时间和空间上的性能,但驻留对象也有所消耗
python提供 intern方法强制2个字符串指向同一个对象。
>>> import sys
>>> a="a*&&"
>>> b="a*&&"
>>> a is b
False
>>> a=sys.intern(b)
>>> a is b
True
python中整形对象存储的位置
在python中,整形对象存储的位置有所不同,有些整形是预先分配的,一致在内存里,而其他的则在使用时开辟空间,对于[-5,256]之间的整数数字,python默认驻留,即预先在内存中分配。
is 与 == 的区别
== 比较左右两端的值是否相等
is 判断的是左右两端内容的内存地址是否相等,如果返回True,那么判定比较的两个变量使用的是同一个地址,同一个对象。
id函数的作用:用来查看开辟的空间所对应的地址,返回传入对象的虚拟内存地址的整数值。
lst1 = [1, 2, 3]
lst2 = [1, 2, 3]
print(lst1 == lst2) # True
print(lst1 is lst2) # False
a = 'hahah'
b = 'hahah'
print(a == b) # True
print(a is b) # True 大整数池的概念
总结:如果内存地址相同,那么值一定相同,如果值相同,内存地址不一定相同
二、集合
散列类型用来表示无序的元素的集合
2.1 集合的定义
python中集合的概念与数学中一致,用来表示无序不重复元素的集合,集合中的元素只能是不可变类型。
集合使用一对大括号{}包裹,元素之间使用逗号隔开。
a = {'a', 'b', 'c'}
b = {1, 2, 3, 4}
c = {1, 'a', ('a',1), 1.5} # 元祖中如果有可变类型会报错
d = {a, ['a'],c} # 报错 集合中的元素必须是不可变数据类型
# 空集合 set()
python中集合使用set表示
需要特别注意的是:空集合用 set() 表示
2.2 集合的常用操作
增
- .add(ele) 增加一个.
向集合中添加元素ele,如果不存在则添加,存在则不做操作,没有返回值。
s ={1, 2, 3}
print(s)
s.add(4) # None
print(s)
# {1, 2, 3}
# {1, 2, 3, 4}
- .update(iterable) 增加多个
把序列中的元素添加到集合中去,不存在则添加
s = {1, 2, 3}
s2 = {2, 4, 5} s2 里面的元素必须是不可变的元素
但是s2本身可以是可变的
s.update(s2)
print(s)
# {1, 2, 3, 4, 5} # 集合天生去重
s3 = {1,2}
s3.update([3,4])
print(s3) # {1, 2, 3, 4} # 添加的是可迭代对象中的元素,不受迭代对象整体的影响,只受里面元素的数据类型影响。
s3.update('abc')
print(s3) # {1, 2, 3, 4, 'c', 'b', 'a'}
s3.update([1],2) # 报错 第一个元素是列表是可变的,所以报错。
s3.update([{1,2},2]) # 报错 列表里面的第一个元素是集合,集合是可变数据类型。
s3.update(1, 2) # 报错,必须传入可迭代对象。
要记清楚,update是把可迭代对象中的数据的元素往里面传,记得这一点就可以了。
注意:
①:添加的是可迭代对象中的元素,不受迭代对象类型的影响,只受里面元素的数据类型影响。
可迭代对象,基本数据类型中除了数字类型和布尔类型,其他的都可以迭代。
②:必须传入可迭代对象,不然会报错。
例题·:
删
- .pop() 随机删除并返回集合中的一个元素,如果集合为空则抛出异常
s = {'a', 'b', 'c'}
res = s.pop()
print(res) # a
print(s) # {'c', 'b'}
- remove(ele) 从集合中删除元素ele如果不存在则报错,没有返回值
s = {1, 2, 3, 4}
res = s.remove(1)
print(s) # {2, 3, 4}
- discard(ele) 与remove 作用一致,但是如果不存在,不会报错。
- clear()清空 集合变成 set() 空集合
- 集合没有改 ,因为集合没有顺序
2.3 集合的运算
交集 &
取既属于集合A和又属于集合B的项组成的集合叫做AB的交集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s = s1 & s2
print(s) # {2, 3}
并集 |
集合A和集合B的所有的元素组成的集合称为集合A与集合B的并集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s = s1 | s2
print(s) # {1, 2, 3, 4}
相对补集(差集) -
取在集合A中不在集合B中的项组成的集合称为A相对于B的补集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s = s1 - s2
print(s) # 1
对称差集(交集的反集)
取不在集合AB交集里的元素组成的集合称为对称差集,也叫反交集
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s = s1 ^ s2
print(s) # {1, 4}
2.4 集合去重
集合具有天生去重的性质,因此可以利用它来去除序列中的重复元素
ls = [1,1,2,3,4,4,3,2,5] # 序列中必须是不可变元素
ls = list(set(ls))
print(ls) # [1, 2, 3, 4, 5]
a ='aabbcc'
res = set(a)
print(res) # {'c', 'b', 'a'} 去掉重复元素
当把字符串类型转换成集合类型时,会把字符串中的单个字符分别作为集合中的元素。