• 集合-缓存机制-深浅copy


    一、is id == 用法

    is 判断的是内存地址是否相同

    id 查看内存地址:id相同,值一定相同,值相同,id不一定相同

    == 比较判断是否相等

    l1 = [1, 2, 3]
    l2 = [1, 2, 3]
    ​
    print(l1 is l2)  # False

    二、代码块

    我们所有的代码都需要依赖代码执行

    一个文件就是一个代码块

    Python程序是由代码块构造的。块是一个Python程序的文本,他是作为一个单元执行的。

    代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。

    而作为交互方式输入的每个命令都是一个代码块。

    互方式就是咱们在cmd中进入Python解释器里面,每一行都是一个代码块。列如:这是两个代码块

    Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 16:33:24) [MSC v.1928 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> li = 100
    >>> ls = 200
    >>>

    对于一个文件中的两个函数,也分别是两个不同的代码块:

    def  func():
        pass
    def funcl():
        pass
    # 这是两个代码块

    三、同一代码块下的缓存机制

    前提条件:同一个代码块内

    机制内容:

    Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否存在,如果存在,会将其重用。换句话说:执行同一个代码块时,遇到初始化对象(是指的是新建一个变量)的命令时,他会将初始化的这个变量与值存储在一个字典中(内存字典中),在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个字典中的之前的这个值。所以在你给出的例子中,文件执行时(同一个代码块)会把li、ls两个变量指向同一个对象,满足缓存机制则他们在内存中只存在一个,即:id相同

    li = 100     # 储存在内存字典中了为{'li':100}
    ls = 100     # 内存字典中有了,拿出来给ls
    print(li is ls)
    ​
    True #li和ls的id相同

    适用的对象:int bool str

    具体细则:所有的数字,bool,几乎所有的字符串(了解)

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

    四、不同代码块下的缓存机制(叫小数据池)

    1、Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好了的缓存对象。

    2、Python会将一定规则的字符串储存在字符串驻留池中,当你将这些字符串赋值给变量时,并不会重新创建对象,而是使用在字符串驻留池中创建好的对象。

    内存中会自动创建两个内存空间,一个空间为-5~256的所有数字叫做缓存,另一个空间为一定规则的字符串叫做字符串驻留池,这两个合起来叫做小数据池(容器,或字典)

    当在不同代码块中创建对象(定义变量)时,无论这些变量指向这些范围内的整数或者字符串,那么它就直接在这个 “池” 中引用。

     

    提前条件:不同的代码块

    适用对象:int bool str

    具体细则:-5~256, bool,满足规则的字符串

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

    Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 16:33:24) [MSC v.1928 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> ls = 800
    >>> li = 800
    >>> print(ls is li)
    False
    >>># 为什么是False呢?这是交互式方式,每一行都是一个代码块,因为 800 不在小数据池内,小数据池数字范围是 -5~256 所以 ls 和 li 的内存地址不相等
    ​
    Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 16:33:24) [MSC v.1928 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> ls = 200
    >>> li = 200
    >>> print(ls is li)
    True
    >>># 200在 小数据池数字范围 -5~256 之内,所以id相等

    五、缓存机制总结

    同一个代码下适用一个缓存机制,不同的代码块下适用另一缓存机制叫(小数据池)

    小数据池:数字范围是 -5~256

    缓存机制的优点:提升性能,节省内存

    六、集合(了解)

    Python基础数据类型:集合set。容器型的数据类型,它要求它里面的元素是不可变的数据,但是它本身是可变的数据类型。集合是无序的。{}

    集合的作用:列表的去重,关系测试:交集,并集,差集

    创建

    se = set({'a', 'ad', 4, 55, 2}) # 不常用
    ​
    se = {'a', 'ad', 4, 55, 2}

    空集合

    se = set()

    集合的有效性测试,集合的元素是不可变的

    se = {['a', 'b'], 'ad', 4, 55, {'are': 1}} # ['a', 'b']可变
    print(se)
    # 报错    
    # se = {['a', 'b'], 'ad', 4, 55, {'are': 1}}
    # TypeError: unhashable type: 'list'

    七、集合的增删改

    add()

    se = {'小米', '明明', '红米', 'alex'}
    se.add('xx')
    print(se)  # {'明明', 'xx', '小米', 'alex', '红米'}

    updata() 迭代者增加,每个元素都增加,有重复的去重

    se = {'小米', '明明', '红米', 'alex'}
    se.update('aabcde')
    print(se)   # {'c', '明明', 'b', 'e', '红米', 'a', 'alex', '小米', 'd'}

    remove() 按照元素去删除

    pop() 随机删除

    clear() 清空

    改(变相改,先删除在新增加)

    se = {'小米', '明明', '红米', 'alex'}
    se.remove('小米')
    se.add('牛奶')
    print(se)  # {'明明', '牛奶', '红米', 'alex'}

    八、集合的其他操作(关系测试)

    交集 (& 或 intersection)都有的

    se = {1, 2, 3, 56, 2, 4, 2, 4}
    ei = {1, 5, 2, 66, 4, 5, 9, 4}
    print(se & ei)              # {1, 2, 4}
    print(se.intersection(ei))    # {1, 2, 4}

    并集。 (| 或者 union) 合并在一起

    se = {1, 2, 3, 56, 2, 4, 2, 4}
    ei = {1, 5, 2, 66, 4, 5, 9, 4}
    print(se | ei)            # {1, 2, 3, 4, 66, 5, 9, 56}
    print(se.union(ei))        # {1, 2, 3, 4, 66, 5, 9, 56}

    差集。 ( - 或 difference)

    se = {1, 2, 3, 56, 2, 4, 2, 4}
    ei = {1, 5, 2, 66, 4, 5, 9, 4}
    print(se - ei)                    # {56, 3}
    print(se.difference(ei))        # {56, 3}

    反交集。 ( ^ 或者 symmetric_difference ) 除了两个集合都有的之外的

    se = {1, 2, 3, 56, 2, 4, 2, 4}
    ei = {1, 5, 2, 66, 4, 5, 9, 4}
    print(se ^ ei)                            # {66, 5, 3, 56, 9}
    print(se.symmetric_difference(ei))        # {66, 5, 3, 56, 9}

    子集。( < )被包含于

    se = {1,2,3}
    si = {1,2,3,4,5,6}
    print(se < si)  # True  se包含于si则返回True,否则返回False

    超集。( > ) 包含于

    se = {1, 2, 3}
    si = {1, 2, 3, 4, 5, 6}
    print(si > se)  # False  si包含se则返回True,否则返回False
    列表的去重 集合去重(面试题) 不能保持原来顺序的
    li = [1, 1, 2, 2, 3, 3, 5, 6, 4, 4, 8]
    se = set(li)
    li = list(se)
    print(li)   # [1, 2, 3, 4, 5, 6, 8]

    用处:数据之间的管理,列表去重。

    九、深浅copy

    浅copy

    浅copy会在内存中新开辟一个空间,存放这个copy的列表,但是列表里面的内容还是沿用之前对象的内存地址所以 l1 , l2 的id不同,但是内容id相同

    总结就是:copy一个外壳,里面的所有内容都指向原来的。id相同

    l1 = [1, 2, 3, [22, 33]]
    l2 = l1.copy()
    print(l1, 'l1的内存id:' + str(id(l1)) + ' 内容id:' + str(id(l1[3])))
    print(l2, 'l2的内存id:' + str(id(l2)) + ' 内容id:' + str(id(l2[3])))
    
    # 输出
    [1, 2, 3, [22, 33]]   l1的内存id:35342088   内容id:35358632
    [1, 2, 3, [22, 33]]   l2的内存id:35359752   内容id:35358632

    深copy

    互相独立的,但是:深copy的特性就是将可变的数据类型在内存中重新创建一份,而不可变的数据类型就沿用之前的,列如:

    import copy
    l1 = [1, 2, 3, [22, 33]]
    l2 = copy.deepcopy(l1)
    print('[22, 33]的内容id:'+str(id(l1[3]))+'  2的内容id:'+str(id(l1[1])))
    print('[22, 33]的内容id:'+str(id(l2[3]))+'  2的内容id:'+str(id(l1[1])))
    
    # 输出
    [22, 33]的内容id:32868104  2的内容id:30371984
    [22, 33]的内容id:32868808  2的内容id:30371984

    总结:深copy则会在内存中开辟新空间,将原列表以及列表里面的可变的数据类型重新创建一份,不可变的数据类型则沿用之前的。

    学习之旅
  • 相关阅读:
    读书计划
    《梦断代码》读书笔记1
    合作项目5
    合作项目4
    合作项目3
    电梯调度需求分析
    合作项目2
    四则运算3程序
    合作编程
    四则运算某模块程序测试
  • 原文地址:https://www.cnblogs.com/XiaoYang-sir/p/14639178.html
Copyright © 2020-2023  润新知