1 内容总览
- is == id 用法
- 代码块
- 同一代码块下的缓存机制 (字符串驻留机制)
- 不同代码块下的缓存机制 (小数据池)
- 总结
- 集合(了解)
- 深浅copy
2 具体内容
- id is ==
# id 获取对象的内存地址,内存地址就相当于人的身份证号,唯一且不可变 # i = 100 # s = 'alex' # print(id(i)) #1892120688 # print(id(s)) #2707107640912 # == 比较的是两边的值是否相等 l1 = [1, 2, 3] l2 = [1, 2, 3] print(l1 == l2) #True s1 = 'alex' s2 = 'alex ' print(s1 == s2) #False,s2有空格 # is 判断的是内存地址是否相同 # l1 = [1, 2, 3] # l2 = [1, 2, 3] # print(id(l1)) #2747199417864 #每次打印都会重新分配内存空间,故每次打印出来的id都不同(随机的) # print(id(l2)) #2747199444168 # print(l1 is l2) #False,因为list是可变数据类型 # s1 = "123" # s2 = "123" # print(id(s1)) #2747198568016 # print(id(s2)) #2747198568016 #虽这2个id同,但每次打印id依然会变,因为也是随机分配内存空间 # print(s1 is s2) #True,因为str是不可变数据类型,此时的str是同一个人 # s1 = "123" # s2 = "13" # print(id(s1)) #1320051373648 # print(id(s2)) #1320081191912 #每次打印id均会变,因为是各自随机分配内存空间(可变数据..也如此) # print(s1 is s2) #False,此时是两个不同的str #注意:id相同(不可变数据类型),值一定相同;值相同,id不一定相同(可变数据类型的id不同,不可变..的id相同) s1 = 'alex' s2 = 'alex' print(id(s1)) #2368632501168 print(id(s2)) #2368632501168 print(s1 is s2) #id相同,值一定相同 #True # 值相同,id不一定相同 l1 = [1,2,3] l2 = [1,2,3] print(l1 == l2) #值相同 True print(l1 is l2) #id不同 False #因为list是可变数据类型啊,及时值相同,id也不会同 s1 = '123' s2 = '123' print(s1 == s2 ) #值相同 True print(s1 is s2) #id也相同 True #因为str是不可变数据类型,值相同,即是同一个人,故id是同一个,即 #s1和s2共用同一个内存地址() ##粘张图上去-见文件夹截图
- 代码块
- 代码块:我们所有的代码都需要依赖代码块执行。
- 一个文件 ( 模块,函数,类 )就是一个代码块 - pycharm里。
- 交互式命令下(终端中-小黑框)一行就是一个代码块。
- 两个机制: 同一个代码块下,有一个机制。不同的代码块下,遵循另一个机制。
- 同一个代码块下的缓存机制: 字符串驻留机制。-(就是一个盛着int bool str 的缸(计算机默认将数据放到dict里))
- 前提条件:同一个代码块内。
- 机制内容:pass-(先检查这个缸(其实只个dict)里有没有要调用的数据,如果有,则直接调用,不再在内存中开辟新的内存空间;如果没有,再创建)
- 适用的对象: int bool str
- 具体细则:所有的数字,bool,几乎所有的字符串。
- 优点:提升性能,节省内存。
- 不同代码块下的缓存机制: 小数据池。
- 前提条件:不同代码块内。
- 机制内容:pass-(先检查这个缸( 计算机其实是将这些数据全部存在了一个dict里 )里有没有要调用的数据,如果有,则直接调用,不再在内存中开辟新的内存空间;如果没有,再创建)
- 适用的对象: int bool str
- 具体细则:-5~256数字(包含-5和256),bool,满足一定规则的字符串。
- str的具体规则:-补充
- 1.字符串在做乘法的时候总长度不能超过20,否则不会驻留(即不会共用原来的内存) #记住
# a = "alexdsb" * 2 # b = "alexdsb" * 2 # print(a is b) #true # a = "alexdsb" * 5 # b = "alexdsb" * 5 # print(a is b) #False 因为乘出来后,str的长度超过了20
- 2.自己定义的字符串 长度不限制 字符串必须(字母,数字.下划线)组成,进行驻留
- 3.特殊字符(中文除外)定义1个的时候,进行驻留
- 4.字符串*1 其实就是赋值
- 1.字符串在做乘法的时候总长度不能超过20,否则不会驻留(即不会共用原来的内存) #记住
- 优点:提升性能,节省内存。
# i1 = 1000 # i2 = 1000 # i3 = 1000 # l1 = [1,2,3] # l2 = [1,2,3] # print(id(l1)) # print(id(l2)) # print(id(i1)) # print(id(i2)) # print(id(i3)) i = 800 i1 = 800 s1 = '[email protected]!#fkdjlsafjdskl;fjds中国' s2 = '[email protected]!#fkdjlsafjdskl;fjds中国' print(i is i1) print(s1 is s2)
- 总结:+
- 面试题考。
- 回答的时候一定要分清楚:同一个代码块下适用一个缓存机制( 字符串驻留机制)。不同的代码块下适用另一个缓存机制(小数据池)
- 小数据池:数字的范围是-5~256.
- 缓存机制的优点:提升性能,节省内存。
- python基础数据类型之:集合 set。容器型的数据类型,它要求它里面的元素是不可变的数据,但是它本身是可变的数据类型。集合是无序的(不支持索引)。{1,2,3}。#其实集合就是1个没有值的字典,里面的元素相当于dict的键,唯一(它)
- 集合的作用:
- 列表的去重。-set天然去重
- 关系测试: 交集,并集,差集,.....
- pass
# 集合的创建: # set1 = set({1, 3, 'Barry', False}) # set1 = {1, 3, '太白金星', 4, 'alex', False, '武大'} # print(set1) # 空集合: # print({}, type({})) # 空字典 # set1 = set() # print(set1) # 集合的有效性测试 # set1 = {[1,2,3], 3, {'name': 'alex'}} # print(set1) #报错,因为set里的元素只能是不可变数据类型(但set本身是可变数据类型) # set1 = {'太白金星', '景女神', '武大', '三粗', 'alexsb', '吴老师'} # 增: # add # set1.add('xx') # print(set1) # update迭代着增加 # set1.update('fdsafgsd') # print(set1) # 删 # remove # remove 按照元素删除 # set1.remove('alexsb') # # print(set1) # pop 随即删除 # set1.pop() # print(set1) # 变相改值 # set1.remove('太白金星') # set1.add('男神') # print(set1) #关系测试:*** # 交集 & # set1 = {1, 2, 3, 4, 5} # set2 = {4, 5, 6, 7, 8} # print(set1 & set2) #输出结果:{4, 5} # 并集: | # set1 = {1, 2, 3, 4, 5} # set2 = {4, 5, 6, 7, 8} # print(set1 | set2) #输出结果:{1, 2, 3, 4, 5, 6, 7, 8} # 差集 - 谁在前就是求谁的差集 # set1 = {1, 2, 3, 4, 5} # set2 = {4, 5, 6, 7, 8} print(set1 - set2) #{1, 2, 3} print(set2 - set1) #{8, 6, 7} 集合是无序的 # 反交集 ^ 除了交集以外的元素 # set1 = {1, 2, 3, 4, 5} # set2 = {4, 5, 6, 7, 8} # print(set1 ^ set2) #输出结果:{1, 2, 3, 6, 7, 8} # 子集 < # set1 = {1,2,3} # set2 = {1,2,3,4,5,6} # print(set1 < set2) #True #代表:问set1是否是set2的子集;即set2里知否全部包含set1的各元素 # print(set2 < set1) #False # 超集 > set1 = {1,2,3} set2 = {1,2,3,4,5,6} print(set2 > set1) #True #问计算机:set2是不是set1的超集 # 冻结集合 -把可变的转换成不可变 #了解 frozenset({1,2,3,4,5}) print() # 列表的去重 *** l1 = [1,'太白', 1, 2, 2, '太白',2, 6, 6, 6, 3, '太白', 4, 5, ] set1 = set(l1) #去重,去谁就用set把谁包起来 #若直接print(set(lst)) 结果:{1, 2, 3, 4} l1 = list(set1) #要再转回成list-用list包起来 #转成什么,就用谁包 print(l1) #[1, 2, 3, 4, 5, 6, '太白'] 或 print(list(set(li))) #[1, 2, 3, 4, 5, 6, '太白'] # set的主要用处:数据之间的关系,列表去重。
- 集合的作用:
- 深浅copy(面试会考)
# 赋值运算 元素共用一个(一个人,id同;一个变了另一个也变),改变的只是指向关系,内存里依然还是那块内存空间,没有开辟新的内存空间。另,变量指向的只能是具体的数据 # l1 = [1, 2, 3, [22, 33]] # l2 = l1 #赋值 # l1.append(666) # print(l1) #[1, 2, 3, [22, 33], 666] # print(l2) #[1, 2, 3, [22, 33], 666] # print(l1 is l2) #True 因为元素是同一个,故id也相同 # 浅copy:在内存中开辟一个新的空间存放copy的对象,里面的所有元素与被copy对象 # 里面的元素均共用一套(即,全部都是那些人,id同.可变and不可变均是共用)。#但只copy第一层(第一层是指l1里的1, 2, 3, [ ], 小列表里的元素属于第2层,没有被copy下来,copy下来的只是一个list的外框- 这就是a的原因-因为copy下来的是框[],故框里的元素改还是加,2者都会变,因为这个框[]是共用的同1个人) # 论变or不变: # a.当改变的是2者(原+copy下来的)中任意一个的可变数据类型的元素时,另一个也会变 l1 = [1, 2, 3, [22, 33]] l2 = l1.copy() #浅copy #l2 = l1[:] #也叫浅copy l1[-1].append(666) print(id(l1[-1])) #3286499421704 print(id(l2[-1])) #3286499421704 小列表的id相同,是因为浅copy共用一套元素 print(id(l1[0])) #1892117520 print(id(l2[0])) #1892117520 只要是浅copy,里面元素全部共用 print(l1) #[1, 2, 3, [22, 33, 666]] print(l2) #[1, 2, 3, [22, 33, 666]] 因为共用一套元素,所以一个变,另一个也变 # b.当改变的是2者中任意一个的不可变数据类型的元素时,另一个不变 l1 = [1, 2, 3, [22, 33]] l2 = l1.copy() #浅copy l1[0] = 90 print(l1) #[90, 2, 3, [22, 33]] print(l2) #[1, 2, 3, [22, 33]] # c.另,若copy后,再往原list里追加元素,则后者不变,因为只copy了追加前的元素.追加后的元素没有copy到 l1 = [1, 2, 3, [22, 33]] l2 = l1.copy() #浅copy l1.append(666) print(l1,id(l1)) #[1, 2, 3, [22, 33], 666] 2600777274568 print(l2,id(l2)) #[1, 2, 3, [22, 33]] 2600777275336 # 深copy:在内存中开辟一个新的空间存放copy的对象,其中不可变数据类型沿用之前的(即共用一套,同一个人,id同),可变数据类型会重新创建新的。但可变数据类型里的元素(第2层)不可变数据类型与原来共用一套,可变数据类型重新创建新的,一次类推到第n层-这就是深copy(可以copy到第n层,但是浅copy却只能copy最外层([],{})) # 论变or不变:无论原来那个,变的是不可变还是可变的元素,后者(copy下来的那个)均不变 # import copy # l1 = [1, 2, 3, [22, 33]] # l2 = copy.deepcopy(l1) # # print(id(l1)) #2886964838728 # # print(id(l2)) #2886964840008 # l1[-1].append(666) # print(l1) #[1, 2, 3, [22, 33, 666]] # print(l2) #[1, 2, 3, [22, 33]] #深浅copy用在哪:1.面试;2.当原数据的内存地址要求不能改变时-(此时,你可先深copy一份下来,再做其他操作,因为copy下来的这份跟原来的那份数据的内存地址是完全不同的2个,故对它进行修改不会对原有数据进行改变) # 相关面试题: # 面试题1: import copy a = [1,2,3,[4,5],6] b = a #赋值 共用一个元素,一个变,另一个也变 c = copy.copy(a) #浅copy,当改变的是2者(原+copy下来的)中任意一个的可变数据类型元素时,另一个也会变 d = copy.deepcopy(a) #深copy b.append(10) c[3].append(11) d[3].append(12) print(a) #a = [1,2,3,[4,5,11],6,10] print(b) #b = [1,2,3,[4,5,11],6,10] print(c) #c = [1,2,3,[4,5,11],6] print(d) #d = [1,2,3,[4,5,12],6] # 面试题2: # l1 = [1, 2, 3, [22, 33]] # l2 = l1[:] #赋值 # l1[-1].append(666) # print(l1) #[1, 2, 3, [22, 33, 666]] # print(l2) #[1, 2, 3, [22, 33, 666]] # 浅copy: list dict: 嵌套的可变的数据类型是同一个。 # 深copy: list dict: 嵌套的可变的数据类型不是同一个 。
03 小结(重要-你懂的)
- id is == 三个方法要会用,知道是做什么的。
- 回答的时候一定要分清楚:同一个代码块下适用一个缓存机制。不同的代码块下适用另一个缓存机制(小数据池)
- 小数据池:数字的范围是-5~256.
- 缓存机制的优点:提升性能,节省内存。
- 集合:列表去重,关系测试。
- 深浅copy:理解浅copy,深浅copy,课上练习题整明白。
- 小数据池在哪用: 面试 + 平时解决自己疑惑 的时候想它。
原文地址:https://www.cnblogs.com/wanshizidiao/p/11005290.html
时间: 2024-11-29 08:25:59