zoukankan      html  css  js  c++  java
  • 铁乐学Python_day07_集合and浅谈深浅copy

    1、【List补充】

    在循环一个列表时,最好不要使用元素和索引进行删除操作,一旦删除,索引会随之改变,容易出错。
    如果想不出错,可以采用倒着删除的方法,因为倒着删除进行的话,只是后面元素的位置发生了变化(位移),但不影响前面元素的排列位置。

    元组在只有一个元素时,需要加个逗号来防止岐义。

    将列表中索引为奇数的元素进行删除,有三种方法(思路):

    第一种是最简单的del加切片:
    例:

    li = ['老男孩', 'python', 'alex', 'wusir', 'egon', 'ritian', '女神']
    del li[1::2]
    print(li)和步长操作;
    
    结果:['老男孩', 'alex', 'egon', '女神']
    

    第二种是先挑选出索引为偶数的元素(因为反过来说要保留的是它们),
    加进一个新列表,再将新列表赋值给旧列表;

    li = ['老男孩', 'python', 'alex', 'wusir', 'egon', 'ritian', '女神']
    l1 =[]
    for i in range(len(li)):
        if i % 2 == 0:
            l1.append(li[i])
    li = l1
    print(li)
    
    结果:['老男孩', 'alex', 'egon', '女神']
    

    第三种是通过for循环,通过range索引范围找出奇数位置的元素来进行单个单个的del,但是要注意的是要将范围倒过来进行操作,如下:

    li = [11, 22, 33, 44, 55]
    for i in range(len(li)-1, -1, -1):
        if i % 2 == 1:
            del li[i]
    print(li)
    
    结果:[11, 33, 55]
    

    注意不要使用index查找元素来确定索引的方式,因为一旦列表中有多个同名的元素存在时,index就会导致错误,和你预想中的效果不一样,index查找返回的是第一个找到的元素的索引位置。

    2、【dict补充】

    题:删除以下字典中,键包含k的键值对。
    dic = {'k1':'value1', 'k2':'value2', 'name':'wusir'}

    假如我们试图for遍历键直接去删除的话:

    dic = {'k1':'value1', 'k2':'value2', 'name':'wusir'}
    for i in dic:
        print(i)
        if 'k' in i:
            del dic[i]
    print(dic)
    
    会出现如下报错:
    Traceback (most recent call last):
    k1
      File "E:/Python/day07/temp.py", line 20, in <module>
        for i in dic:
    RuntimeError: dictionary changed size during iteration
    

    这是因为,
    在循环(迭代)字典时,是不能进行改变字典大小的操作的(增加或删除此字典的键值对)。

    故可行的是先将所有键取出放在一个列表中,再循环这个列表来进行删除。

    li =[]
    for i in dic:
        if 'k' in i:
            li.append(i)
    for k in li:
        del dic[k]
    print(dic)
    
    {'name': 'wusir'}
    
    以上代码其实还可以优化成不用先行创建空列表,而是直接list转换查询到的所有键的dict.keys()容器成列表,如下:
    
    dic = {'k1':'value1', 'k2':'value2', 'name':'wusir'}
    
    lis =list(dic.keys())
    for key in lis:
    	if 'k' in key:
    		del dic[key]
    print(dic)
    
    另,数据转换补充
    tuple <---> list
    List(tuple)
    tuple(list)
    

    3、【集合set】

    从事数据开发的可能常用到它
    集合的样子,如:set = {11, 22, 33}

    集合:
    数据类型:里面的元素不重复,无序(意味着没有索引,不能改,可以增删查),它里面的元素是可hash的,但集合本身是不可哈希的,不能作为字典的key。

    作用:
    1、去重。
    (面试必有一道去重题,不提算法的情况下,直接转换成集合)
    2、数据关系的测试。(两个集合之间的交并集等)

    li = [11,11,22,22,55,55,66,66,33,33,33,44]
    li = list(set(li))
    print(li)
    
    增加:
    set.add()
    hum = {'枪兵', '弓箭手', '狮鹫', '剑士'}
    hum.add('僧侣')
    print(hum)
    {'枪兵', '弓箭手', '僧侣', '狮鹫', '剑士'}
    
    set.update(迭代增加)
    hum = {'枪兵', '弓箭手', '狮鹫', '剑士'}
    soldires = ['骑士', '天使', '僧侣']
    hum.update(soldires)
    print(hum)
    {'剑士', '僧侣', '骑士', '狮鹫', '天使', '枪兵', '弓箭手'}
    
    删除:
    set.remove()按照元素去删除,删除不存在的元素会引发异常
    hum = {'枪兵', '弓箭手', '狮鹫', '剑士'}
    hum.remove('枪兵')
    print(hum)
    {'狮鹫', '弓箭手', '剑士'}
    
    set.discard()删除集合指定的元素,删除不存在的元素不会引发报错(它什么都不做)
    
    set.pop()随机删除(因为无序),有返回值,返回被删除的值
    hum = {'枪兵', '弓箭手', '狮鹫', '剑士'}
    print(hum.pop())
    print(hum)
    剑士
    {'狮鹫', '弓箭手', '枪兵'}
    
    set.clear()  清空集合【空集合表现为set()】
    hum = {'枪兵', '弓箭手', '狮鹫', '剑士'}
    
    hum.clear()
    print(hum)
    set()
    
    del set 删除整个集合
    
    查: 
    for遍历去查询所有元素
    for i in set:
    		print(i)
    
    # 求交集 (求两个集合中都有的元素)
    set1 & set2
    set1.intersection(set2)
    
    例:
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    print(set1 & set2)   # 显示{1, 4, 5}
    print(set1.intersection(set2))  # 显示{1, 4, 5}
    
    # 反交集 (反过来返回两个集合中交集除外的元素)
    set1 ^ set2
    set1.symmetric_difference(set2)
    
    例:
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    print(set1 ^ set2)    # 显示{2, 3, 6, 7}
    print(set1.symmetric_difference(set2)) # 显示{2, 3, 6, 7}
    
    # 计算交集并更新成交集操作
    intersection_update
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    set1.intersection_update(set2)
    print(set1)
    {1, 4, 5}
    set1集合变成了交集的元素。
    
    # 并集 (合并,相同的被覆盖)
    set1 | set2 (且去重)
    set1.union(set2)
    
    例:
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    print(set1 | set2)
    print(set1.union(set2))
    # 显示:
    {1, 2, 3, 4, 5, 6, 7}
    {1, 2, 3, 4, 5, 6, 7}
    
    # 并集计算并更新成并集
    set1.update(set2)
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    set1.update(set2)
    print(set1, set2)
    {1, 2, 3, 4, 5, 6, 7} {1, 4, 5, 6, 7}
    可以看到只有前者被替换成了并集。
    
    # 差集 (前者减去后者中有的前者元素,所剩的集合)
    set1 - set2
    set2 - set1
    set1.difference(set2)
    
    例:
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    print(set1 - set2) #显示{2, 3}
    print(set2 - set1) #显示{6, 7}
    
    # 差集更新
    set1.difference_update(set2)
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    set1.difference_update(set2)
    print(set1, set2)
    {2, 3} {1, 4, 5, 6, 7}
    set1被替换成set1和set2的差集了。也就是它不但计算两者的差集,同时还将差集结果替换前者集合。
    
    # 对称差集,计算两两之间的差集,返回的是合起来的差集结果集合
    symmetric_difference() 
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    
    print(set1.symmetric_difference(set2))
    {2, 3, 6, 7}
    
    # 子集 (返回bool值)
    set1.issubset(set2)
    set1 < set2
    
    例:
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    print(set1 < set2)     # 返回False
    
    set3 = {33, 35, 38}
    set4 = {21, 22, 33, 35, 38}
    print(set3.issubset(set4)) 
    # 返回True,set3是set4的子集,换言之,set4中的元素中包含有set3的所有元素。
    
    # 超集 
    set2.issuperset(set1)
    set2 > set1
    
    例:
    
    set3 = {33, 35, 38}
    set4 = {21, 22, 33, 35, 38}
    
    print(set3.issuperset(set4)) # False
    print(set4 > set3)  # True
    
    # frozenset (冰冻集合)
    
    冰冻集合是一种特殊的集合类型,也是集合(集合是列表的话,冰冻集合就是元组)
    (将集合变成字典键,不可变类型的集合)
    frozenset(set)
    set3 = {33, 35, 38}
    set4 = {21, 22, 33, 35, 38}
    
    print(frozenset(set3), type(frozenset(set3)))
    dic = {frozenset(set4):'test'} #转化成字典键值
    print(dic)
    print(set3, type(set3))
    
    frozenset({33, 35, 38}) <class 'frozenset'>
    {frozenset({38, 33, 35, 21, 22}): 'test'}
    {33, 35, 38} <class 'set'>
    
    基本的集合推导式
    >>> var ={'centos', 'openSUSE', 'Ubuntu', 'reahat'}
    >>> result = {'*'+i+'*' for i in var}
    >>> print(result)
    {'*centos*', '*openSUSE*', '*Ubuntu*', '*reahat*'}
    
    带条件判断的集合推导式
    >>> result = {i for i in var if i !='centos'}
    >>> print(result)
    {'Ubuntu', 'openSUSE', 'reahat'}
    
    多循环集合推导式
    >>> colors = {'red', 'blue', 'pink'}
    >>> sizes = {36, 37, 38, 39}
    >>> result = {c + str(s) for c in colors for s in sizes}
    >>> print(result)
    {'pink37', 'red38', 'pink39', 'pink36', 'red37', 'blue39', 'blue38', 'blue37', 'blue36', 'pink38', 'red39', 'red36'}
    
    # isdisjoint() 检测2个集合是否不存在交集  存在交集则返回False
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 1}
    set3 = {8, 9, 10}
    print(set1.isdisjoint(set2))
    print(set2.isdisjoint(set3))
    False
    True
    

    4、【深浅copy】浅谈

    # copy 不再是指向同一个内存空间,而是在内存中又开辟了新的另一个内存空间
    l1 = [1, 2, 3]
    l2 = l1.copy()
    l1.append(4)
    print(l1, l2)
    
    #copy,对于浅copy来说,第一层创建的是新的内存地址,从第二层开始以及更深层来说,它们用的是同一个(会保持一致性)。
    
    #对于切片来说,它也是一种浅copy
    
    l1 = [1, 2, [1, 2, 3], 4]
    l2 = l1.copy()
    l1[2].append(5)
    print (l1, l2)
    
    # deep.copy 深copy
    # 改变任意一个的任何元素,不管多少层嵌套(几维),它都是新开辟了内存空间,独立存在的。
    improt copy
    l1 = [1, 2, [1, 2, 3], 4]
    l2 = copy.deepcopy(l1)  
    #创建了一个一模一样,但内存空间完全没有关系的,
    l1[2].append(5)
    print(l1, l2)
    print(id(l1[2]),id(l2[2])
    

    Python中对象的赋值都是传递了对象引用(同一内存地址);
    使用copy.copy()进行对象的浅拷贝,它复制了对象,但对于对象中的嵌套(多维)元素,依然使用原始的引用;
    使用copy.deepcopy()进行深拷贝,可以做到复制一个容器(有嵌套)对象,
    使它里面的所有元素(包含元素的子元素)都是开辟新的内存空间;
    对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有被拷贝一说,
    因为对原字符串的操作都会生成新的字符串;
    如果元祖变量只包含原子类型对象,则不能深拷贝。

    5、编码的补充

    s = 'tiele'
    s1 = s.encode('utf-8')      unicode ---> utf-8 转码
    s2 = s1.decode('utf-8')     utf-8 --->unicode  解码
    
    gbk ----> utf-8
    两者不能直接进行转换, 都需要借助unicode
    s = 'tiele'
    s1 = s.encode('gbk')
    s2 = s1.decode('gbk')
    s3 = s2.encode('utf-8')
    或
    s2 = s1.decode('gbk').encode('utf-8')
    

    end

  • 相关阅读:
    hdoj2187:悼念512汶川大地震遇难同胞 (贪心)
    2.0其它之Transform详解,以及UIElement和FrameworkElement的常用属性
    2.0外观之样式, 模板, 视觉状态和视觉状态管理器
    2.0图形之Ellipse, Line, Path, Polygon, Polyline, Rectangle
    2.0控件之ListBox, MediaElement, MultiScaleImage, PasswordBox, ProgressBar, RadioButton
    2.0画笔之SolidColorBrush, ImageBrush, VideoBrush, LinearGradientBrush, RadialGradientBrush
    2.0图形之基类System.Windows.Shapes.Shape
    2.0交互之鼠标事件和键盘事件
    2.0控件之ScrollViewer, Slider, StackPanel, TabControl, TextBlock, TextBox, ToggleButton
    2.0交互之InkPresenter(涂鸦板)
  • 原文地址:https://www.cnblogs.com/tielemao/p/8659886.html
Copyright © 2011-2022 走看看