is == id 的用法;代码块;深浅copy;集合

1 内容总览

  1. is == id 用法
  2. 代码块
  3. 同一代码块下的缓存机制 (字符串驻留机制)
  4. 不同代码块下的缓存机制 (小数据池)
  5. 总结
  6. 集合(了解)
  7. 深浅copy

2 具体内容

  1. 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共用同一个内存地址() ##粘张图上去-见文件夹截图
  2. 代码块

    • 代码块:我们所有的代码都需要依赖代码块执行。
    • 一个文件 ( 模块,函数,类 )就是一个代码块 - pycharm里。
    • 交互式命令下(终端中-小黑框)一行就是一个代码块。
  3. 两个机制: 同一个代码块下,有一个机制。不同的代码块下,遵循另一个机制。

  4. 同一个代码块下的缓存机制: 字符串驻留机制。-(就是一个盛着int bool str 的缸(计算机默认将数据放到dict里))

    • 前提条件:同一个代码块内。
    • 机制内容:pass-(先检查这个缸(其实只个dict)里有没有要调用的数据,如果有,则直接调用,不再在内存中开辟新的内存空间;如果没有,再创建)
    • 适用的对象: int bool str
    • 具体细则:所有的数字,bool,几乎所有的字符串。
    • 优点:提升性能,节省内存。
  5. 不同代码块下的缓存机制: 小数据池。

    • 前提条件:不同代码块内。

    • 机制内容: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 其实就是赋值

    • 优点:提升性能,节省内存。

    # 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 = 'hfdjka6757fdslslgaj@!#fkdjlsafjdskl;fjds中国'
    s2 = 'hfdjka6757fdslslgaj@!#fkdjlsafjdskl;fjds中国'
    print(i is i1)
    print(s1 is s2)
  6. 总结:+

    1. 面试题考。
    2. 回答的时候一定要分清楚:同一个代码块下适用一个缓存机制( 字符串驻留机制)。不同的代码块下适用另一个缓存机制(小数据池)
    3. 小数据池:数字的范围是-5~256.
    4. 缓存机制的优点:提升性能,节省内存。
  7. 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的主要用处:数据之间的关系,列表去重。
  8. 深浅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,课上练习题整明白。
  • 小数据池在哪用: 面试 + 平时解决自己疑惑 的时候想它。

猜你喜欢

转载自www.cnblogs.com/wanshizidiao/p/11005290.html
id