zoukankan      html  css  js  c++  java
  • python基础学习day6 copy set

    代码块、缓存机制、深浅拷贝、集合

    • id、is、==
    1. id: 可类比为身份号,具有唯一性,若id 相同则为同一个数据。
    #获取数据的内存地址(随机的地址:内存临时加载,存储数据,当程序运行结束后,内存地址即被丢弃):
    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    #比较的是两边的值是否相等。
    
    1. is 判断id是否相同 (‘’==’‘判断值是否相同
    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在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,如果存在,会将其重用。换句话说:执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中,在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个字典中的之前的这个值,即:id相同。

        适用对象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的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。

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

          其实,无论是缓存还是字符串驻留池,都是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),嵌套的不可变的数据类型是同一个id,可变类型也是同一个id。

      深copy:(list,dict),嵌套的不可变的数据类型是同一个id,嵌套的可变的数据类型不是同一个id。

    l1 = [1,2,['a']]
    l2 = l1[:]
    l1[-1].append(3)
    print(l2)
    >>>[1,2,['a',3]]  #切片是浅copy
    
    import copy
    l1 = [1,2,[3,4]]
    l2 = copy.copy(l1)
    l3 = copy.deepcopy(l1)
    print(l1[0] is l2[0])
    >>>True     
    print(l2[0] is l3[0])
    >>>True
    print(l3[0] is l1[0])
    >>>True
    print(l1[2] is l2[2])
    >>>False
    print(l1 is l2)
    >>>False
    print(l3 is l1)
    >>>False
          #无论是浅copy还是深copy,都会创建一个新的数据类型,但是数据类型中的不可变数据类型都是同一个(id相同),深copy的可变数据类型不是同一个(id不同)。
    

    补充内置函数:

    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}]
    
    
    import copy
    l1 = [1,2,{'name':'山就在那儿','number':[3,4,5]},6,7]
    l2 = copy.deepcopy(l1)
    print(l1[2] is l2[2])   #False
    print(l1[2]['name'] is l2[2]['name'])   #True  #同一代码块下的缓存机制,只适用于不可变对象
    print(l1[2]['number'] is l2[2]['number'])  #False
    l1[2]['name']='a'
    print(l1[2])
    {'name': 'a', 'number': [3, 4, 5]}
    print(l2[2])
    {'name': '山就在那儿', 'number': [3, 4, 5]}
    
  • 相关阅读:
    结对开发地铁
    学习进度04
    构建之法阅读笔记02
    学习进度03
    构建之法阅读笔记01
    Golang开发工具LiteIDE使用方法整理
    package httputil
    package net
    package json
    package encoding
  • 原文地址:https://www.cnblogs.com/wby-110/p/12507988.html
Copyright © 2011-2022 走看看