代码块、缓存机制、深浅拷贝、集合html
#获取数据的内存地址(随机的地址:内存临时加载,存储数据,当程序运行结束后,内存地址即被丢弃): i = 'a' print(id(i)) >>>2047746570672 print(id(i)) >>>2020558633392 print(id(i)) print(id(i)) >>>1908036008368 1908036008368 l1 = [1,2,3] l2 = [1,2,3] print(l1 == l2) >>>True #比较的是两边的值是否相等。
l1 = [1,2,3] l2 = [1,2,3] print(l1 is l2) >>>False #判断的是内存地址是否相同。 print(id(l1)) print(id(l2)) >>>2648963830216 2648963830728 l1 = [1,2,3] l2 = l1 print(l1 is l2) print(id(l1)) print(id(l2)) >>>True 2053863395784 2053863395784 s1 = 'iam' s2 = 'iam' print(s1 is s2) >>>True print(id(s1)) print(id(s2)) >>>2188534085552 2188534085552
id相同,值必定相同,值相同,id不必定相同。python
代码块:python的程序是由代码块构造的。块是一个python程序的脚本,它是做为一个单元执行的。一个模块,一个函数,一个类,一个文件等都是代码块。而做为互交命令方式输入的每一个命令都是一个代码块。两个机制:若是在同一代码块下,则采用同一代码块下的换缓存机制。若是是不一样代码块,则采用小数据池的驻留机制。缓存
同一个代码块的缓存机制(字符串驻留机制):机制内容:Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,若是存在,会将其重用。换句话说:执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中,在遇到新的变量时,会先在字典中查询记录,若是有一样的记录那么它会重复使用这个字典中的以前的这个值,即:id相同。app
适用对象: int(float)::任何数字在同一代码块下都会复用。函数
str:几乎全部的字符串都会符合缓存机制(1,非乘法获得的字符串都知足代码块的缓存机制,,乘法获得的字符串分两种状况:1. 乘数为1时,任何字符串知足代码块的缓存机制,2. 乘数>=2时,仅含大小写字母,数字,下划线,总长度<=20,知足代码块的缓存机制)性能
s1 = 'iam'*1 s2 = 'iam'*1 print(s1 is s2) >>>True
bool:True和False在字典中会以1,0方式存在,而且复用。测试
优势:可以提升一些字符串,整数处理人物在时间和空间上的性能;须要值相同的字符串,整数的时候,直接从‘字典’中取出复用,避免频繁的建立和销毁,提高效率,节约内存。优化
在不一样一个代码块内的缓存机制:小数据池,也称为小整数缓存机制,或者称为驻留机制等等。Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会从新建立对象,而是使用已经建立好的缓存对象。code
python会将必定规则的字符串在字符串驻留池中,建立一份,当你将这些字符串赋值给变量时,并不会从新建立对象, 而是使用在字符串驻留池中建立好的对象。htm
其实,不管是缓存仍是字符串驻留池,都是python作的一个优化,就是将~5-256的整数,和必定规则的字符串,放在一个‘池’(容器,或者字典)中,不管程序中那些变量指向这些范围内的整数或者字符串,那么他直接在这个‘池’中引用,言外之意,就是内存中之建立一个。
适用对象: int(float):那么你们都知道对于整数来讲,小数据池的范围是-5~256 ,若是多个变量都是指向同一个(在这个范围内的)数字,他们在内存中指向的都是一个内存地址。
# pycharm 经过运行文件的方式执行下列代码: 这是在同一个文件下也就是同一代码块下,采用同一代码块下的缓存机制。 i1 = 1000 i2 = 1000 print(i1 is i2) # 结果为True 由于代码块下的缓存机制适用于全部数字 >>>True #经过交互方式中执行下面代码,这是不一样代码块下,则采用小数据池的驻留机制。 >>> i1 = 1000 >>> i2 = 1000 >>> print(i1 is i2) False # 不一样代码块下的小数据池驻留机制 数字的范围只是-5~256.
str:1.字符串的长度为0或者1,默认都采用了驻留机制(小数据池)。2.字符串的长度>1,且只含有大小写字母,数字,下划线时,才会默认驻留。3.用乘法获得的字符串,分两种状况:1 乘数为1,知足规则的字符串,默认驻留。2. 乘数>=2时:仅含大小写字母,数字,下划线,总长度<=20,默认驻留。
#4.指定驻留 from sys import intern a = intern('hello!@'*20) b = intern('hello!@'*20) print(a is b) >>>True #指定驻留是你能够指定任意的字符串加入到小数据池中,让其只在内存中建立一个对象,多个变量都是指向这一个字
bool值就是True,False,不管你建立多少个变量指向True,False,那么他在内存中只存在一个。
# 虽然在同一个文件中,可是函数自己就是代码块,因此这是在两个不一样的代码块下,不知足小数据池(驻存机制),则指向两个不一样的地址。 def func(): i1 = 1000 print(id(i1)) # 2288555806672 def func2(): i1 = 1000 print(id(i1)) # 2288557317392 func() func2()
优势:可以提升一些字符串,整数处理人物在时间和空间上的性能;须要值相同的字符串,整数的时候,直接从‘池’里拿来用,避免频繁的建立和销毁,提高效率,节约内存
参考文章:https://www.cnblogs.com/jin-xin/articles/9439483.html
集合 (set):容器型数据类型,要求它里面的元素是不可变的数据(可哈希),但它自己是可变的数据类型(不可哈希)。集合是无序的。以{}存放数据。
做用:列表的去重;关系的测试(交集,并集…)
/1. 集合的建立:
set = {1,2,'a'} #空集合的表示: set1 = set() #set1 = {}表示空字典
/2 . 增:add update()#迭代增长,有重复的则去重
set1 = {1,2} set1.add('a') print(set1) >>>{'a', 1, 2} #集合无序 set1.update('asdfdsa') print(set1) >>>{'a', 1, 2, 'f', 's', 'd'}
/3. 删:remove()(按照元素删除,pop()随机删除,clear()清空集合 del 删除集合
set1 = {'a', 1, 2, 'f', 's', 'd'} set1.remove('a') print(set1) >>>{1, 2, 's', 'f', 'd'} set1.pop() print(set1) >>>{2, 's', 'f', 'd'} set1.clear() print(set1) >>>{} del set1
/4. 改:先删除再增长
交、并、
/1 . 交集。(&或者intersection) 集合共同有的元素
set1 = {1,2,3} set2 = {2,3,4} print(set1 & set2) #or print(set1.intersection) >>>{2,3}
/2. 并集。(|或者union)集合全部的元素
set1 = {1,2} set2 = {2,3} print(set1 | set2) #or print(set1.union(set2)) >>>{1,2,3}
/3. 差集 ( - 或者difference) ,前一集合独有的元素
set1 = {1,2,3,4,5} set2 = {2,4,6} print(set1 - set2) #or print(set1.difference(set2)) >>>{1,3,5}
/4 . 反交集。(^ 或者symmetric_difference)每一个集合独有的元素
set1 = {1,2,3,4,5} set2 = {3,4,5,6,7} print(set1 ^ set2) #or print(set1.symmetric_difference(set2)) >>>{1,2,6,7}
/5. 子集与超集
set1 = {1,2} set2 = {1,2,3} print(set1 < set2) >>>True print(set1.issubset(set2)) #set1是set2的子集 >>>True print(set2 > set1) >>>True print(set2.issuperset(set1)) #set2是set1的超集 >>>True
/6. frozenset()让集合变为不可变类型
s = frozenset('qweasd') print(s,type(s)) >>>frozenset({'q', 'e', 'w', 's', 'a', 'd'}) <class 'frozenset'>
深浅copy
浅copy:在内存中开辟一个新的空间存放copy的对象(列表、字典),可是里面的全部元素与被copy对象的里面的元素共用一个。
l1 = [1,2] l2 = l1 l1.append(3) print(l2) >>>[1,2,3] #l1,l2两变量指向同一个id(数据) #浅copy l3 = [1,2,['a']] l4 = l3.copy() l3.append(3) print(l3) >>>[1,2,['a'],3] print(l4) >>>[1,2,['a']] l3[-2].append(4) #or l4[-1].append(4) print(l3) >>>[1, 2, ['a', 4], 3] print(l4) >>>[1,2,['a',4]] #l4与l3列表中的数据id是相同的,但l4与l3列表id不相同,即l3中的每一个元素与l4中的每一个元素使用的是相同的一个id,但l4与l3用的不是同一个id。
其实列表第一个一个的槽位,它储存的是对象的内存地址。浅拷贝仍然使用原来的对象的内存地址。对储存的可变对象能够进行更改;若改变不可变类型,则改变的不是不可变类型自己,而是变量的指向关系
深copy,需导入模块copy(浅copy也能够导入copy模块),不可变的数据类型沿用以前的内存地址,可变的数据类型建立新的内存地址。
import copy l3 = [1,2,['a']] l4 = copy.deepcopy(l3) #浅copy为 l4 = copy.copy(l3) l3[-1].append(3) print(l3) >>>[1,2,['a',3]] print(l4) >>>[1,2,['a']] #浅copy输出为 [1,2,['a',3]] #列表第一个一个的槽位,它储存的是对象的内存地址。深拷贝会建立一个新的对象的内存地址。
python对深copy作了一个优化,将对象为不可变数据类型的内存地址沿用同一个,只从新再建立一份可变数据类型的内存地址。
浅copy:(list,dict),嵌套的可变的数据类型是同一个。
深copy:(list,dict),嵌套的可变的数据类型不是同一个。
l1 = [1,2,['a']] l2 = l1[:] l1[-1].append(3) print(l2) >>>[1,2,['a',3]] #切片是浅copy
补充内置函数:
l1 = ['a','b','c'] for i in enumerate(l1,start=50): #start可默认不写 print(i) >>>(50, 'a') (51, 'b') (52, 'c') #小题试作,看代码写结果: #1: l1 = [1,2,3,[4,5]] l2 = [1,2,3,[4,5]] a = l1 == l2 #先看等号右边 b = l1 is l2 print(a) #True print(b) #False #2. data_list = [] for i in range(10): data = {} data['age'] = i data_list.append(data) print(data) >>>{'age': 9} print(data_list) >>>[{'age': 0}, {'age': 1}, {'age': 2}, {'age': 3}, {'age': 4}, {'age': 5}, {'age': 6}, {'age': 7}, {'age': 8}, {'age': 9}] #对比: data_list = [] data = {} for i in range(10): data['age'] = i data_list.append(data) print(data_list) >>>[{'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}]