zoukankan      html  css  js  c++  java
  • python基础 day6 id和is、代码块、集合、深浅拷贝

    一、id is ==

    # id
    # s = 'Jason'
    # print(id(s))  # id的值是随机的
    #
    # l1 = [1, 2, 3]
    # l2 = [1, 2, 3]
    # print(l1 == l2)  # 结果为True,== 比较的是两边的值是否相等
    
    # is 判断的是内存地址是否相同
    l1 = [1, 2, 3]
    l2 = [1, 2, 3]
    print(l1 is l2)  # 结果为false,因为l1和l2分别创建了两个内存地址
    
    s1 = 'Jason'
    s2 = 'Jason'
    print(s1 is s2)  # 结果为True,因为字符串只占一个内存地址
    
    """
    id相同,值肯定相同;
    值相同,id不一定相同
    """
    

    二、代码块

    Python程序是由代码块构造的。块是一个python程序的文本,它是作为一个单元执行的。
    代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。
    作为交互方式(cmd进入python解释器)输入的每个命令都是一个代码块。

    两个机制:同一个代码块下,有一个机制;不同代码块下,遵循另一个机制。

    1. 同一个代码块下的缓存机制:

    ​ 在同一个代码块下遇到初始化对象的命令时,会将初始化的变量和值放在一个字典中,在遇到新的变量时,先到字典中去查找有没有相同的值,如果有,则重复使用该值。

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

    • 适用对象

      int(float):任何数字在同一代码块下都会复用。

      i1 = 1
      i2 = 1
      i3 = 1
      print(i1 is i2 is i3)
      # 结果为True
      

      str:

      1. 非乘法得到的字符串都满足代码块的缓存机制:
      s1 = '三上悠亚 aloha	!@#*('
      s2 = '三上悠亚 aloha	!@#*('
      s3 = '三上悠亚 aloha	!@#*('
      print(s1 is s2 is s3)
      # 结果为True
      
      1. 乘数为1时,任何字符串满足代码块的缓存机制:
      s1 = '三上悠亚 aloha	!@#*(' * 1
      s2 = '三上悠亚 aloha	!@#*(' * 1
      s3 = '三上悠亚 aloha	!@#*(' * 1
      print(s1 is s2 is s3)
      # 结果为True
      
      1. 乘数>=2时:字符串仅包含大小写字母,数字,下划线,相乘之后总长度<=20,满足代码块的缓存机制:
      s1 = '三上悠亚 aloha	!@#*(' * 2
      s2 = '三上悠亚 aloha	!@#*(' * 2
      s3 = '三上悠亚 aloha	!@#*(' * 2
      print(s1 is s2 is s3)
      # 结果为False
      
      s1 = 'Aloha_' * 3
      s2 = 'Aloha_' * 3
      s3 = 'Aloha_' * 3
      print(s1 is s2 is s3)
      # 结果为True
      

      bool:True和False在字典中会以1,0方式存在,并且复用

    2. 不同代码块下的缓存机制:小数据池

    在不同代码块下 数字-5~256 和一定规则的字符串可以复用。
    优点:提升性能,节省内存

    三、集合(set)

    • 集合是一种可迭代的、无序的、不能包含重复元素的数据结构

    • 集合是一种容器型数据类型

    • 集合中的元素都是不可变的(可哈希)元素,而集合本身是可变的数据类型。

      即集合中不能有列表(list)、字典(dict)、集合(set),可以放数字(int)、字符串(str)、布尔值(bool)

    • 集合的作用:1.列表去重

      ​ 2.关系测试:交集、并集、差集

    1. 利用集合的特性给列表去重, 但是不能保持原来的顺序
    list1 = [1, 2, 2, 2, 2, 3, 3, 3, 'jason', 'jason']
    set1 = set(list1)
    list1 = list(set1)
    print(list1)
    
    1. 集合增删改查
    #集合的创建
    set1 = {1, 3, 'jason', True, False}
    print(set1)
    
    
    set1 = {'jason', 'carly', 'aloha'}
    # 增
    # add()
    set1.add('sb')
    print(set1)
    # update()迭代增加
    set1.update('abc')
    print(set1)
    
    # 删
    # remove()按照元素删除
    set1.remove('aloha')
    print(set1)
    # pop()随机删除
    set1.pop()
    print(set1)
    # clear()清空集合
    set1.clear()
    print(set1)
    # del 删除集合
    del set1
    
    # 改(变相改值,先删再加)
    
    1. 集合的交集、并集、差集、反交集
    set1 = {1, 2, 3, 4, 5}
    set2 = {3, 4, 5, 6, 7}
    
    # 交集
    print(set1 & set2)
    print(set1.intersection(set2))
    
    # 并集
    print(set1 | set2)
    print(set1.union(set2))
    
    # 差集
    print(set1 - set2)
    print(set2 - set1)
    print(set1.difference(set2))
    print(set2.difference(set2))
    
    # 反交集
    print(set1 ^ set2)
    print(set1.symmetric_difference(set2))
    
    1. 集合的子集、超集
    set1 = {1, 2, 3}
    set2 = {1, 2, 3, 4, 5, 6}
    
    # 子集
    print(set1 < set2)
    print(set1.issubset(set2))
    
    # 超集
    print(set2 > set1)
    print(set2.issuperset(set1))
    

    四、深浅拷贝

    1.赋值运算

    赋值运算让两个列表的内存地址一样, 即id相同,因此不管是修改list1,还是修改list2,另一个列表也会随之改变

    list1 = [1, 2, 3, [11, 22, 33]]
    list2 = list1
    print(id(list1) == id(list2))
    # 结果为True,此时list1 和list2 的id是一样的
    list1.insert(-1, 666)
    list2.pop(1)
    list1[-1].append(888)
    list2[-1].append(999)
    print(list1)
    print(list2)   # list1 和 list2 结果一样
    

    2.浅copy

    list1 = [1, 2, [11, 22]]
    list2 = list1.copy()
    print(list1 == list2)  # True
    print(id(list1) == id(list2))  # False
    # 浅copy: 值相同,但是id不同
    

    list1被创建的时候,内存中被创建了1,2和[11, 22]这三个元素,
    我们可以理解成这三个元素放在了内存的某个空间里。
    假设list1的id为11111111,则它的三个槽位分别指向这个空间里的1,2,[11, 22]
    此时list1浅copy得到了id为22222222的list2,
    list2的三个槽位也是分别指向这个空间里的1,2,[11, 22]

    # 情况一、如果我们在list1这个列表进行修改,比如追加一个元素,删除一个元素,甚至是清空list1,仅仅是对id为11111111的list1进行了修改,而放在该空间中的1,2,[11, 22]并没有变化。
    # 此时list2中的各个槽位指向的仍是该空间中的1,2,[11, 22],因此list2不会改变。
    list1 = [1, 2, [11, 22]]
    list2 = list1.copy()
    list1.append(3)
    print(list1)  # 结果为[1, 2, [11, 22], 3]
    print(list2)  # 结果为[1, 2, [11, 22]]
    
    # 情况二、如果我们对list1中的[11, 22]进行修改,此时对应在内存中的[11, 22]也会改变。
    # 而list2中的[11, 22]也是指向内存中的[11, 22], 内存中的[11, 22]改变了,因此list2中的[11, 22]也随之改变
    list1 = [1, 2, [11, 22]]
    list2 = list1.copy()
    list1[2].append(666)
    print(list1)
    print(list2)
    

    3.深copy 需要导入copy模块

    import copy
    list1 = [1, 2, [11, 22]]
    list2 = copy.deepcopy(list1)
    print(list1 == list2)
    print(id(list1) == id(list2))
    # 和浅copy一样,值相同,内存地址不同
    

    list1被创建的时候,内存中被创建了1,2,[11, 22]这三个元素, 我们可以理解成这三个元素放在内存的空间一里面
    假设list1的id为11111111,则它的三个槽位分别指向空间一里面的1,2,[11, 22]
    此时list1深copy得到了id为22222222的list2,与浅copy不同的是,此时内存中在一次创建了1,2,[11, 22]这三个元素,并放在了内存的空间二里面
    此时list2的三个槽位分别指向空间二里面的1,2,[11, 22]
    此时对list1进行修改,无论怎么修改,list2始终不变,因为list1和list2此时没有任何的关联

    import copy
    list1 = [1, 2, [11, 22]]
    list2 = copy.deepcopy(list1)
    list1.append(3)
    list1[2].append(666)
    print(list1)  # 结果为[1, 2, [11, 22, 666], 3]
    print(list2)  # 结果为[1, 2, [11, 22]]
    

    注意:前面理解说两个空间里都有 1,2,[11, 22],这是标准的深copy情形。
    但是python做了优化,为了节省内存空间,在python中,int(float) 、str、bool这种不可变的数据类型在内存中只存在一个,因为他们的id都是一样的。

  • 相关阅读:
    富人和穷人的区别(转)
    asp.net主题的几种应用
    asp.net主题的几种应用
    富人和穷人的区别(转)
    SQL SERVER中一些常见性能问题的总结
    SQL SERVER中一些常见性能问题的总结
    Bind和Eval的区别详解
    优酷去广告代码
    使用jquery框架导致js功能失效解决办法
    absolute定位问题
  • 原文地址:https://www.cnblogs.com/west-yang/p/12556540.html
Copyright © 2011-2022 走看看