美文网首页
5. Python之条件判断和深浅copy

5. Python之条件判断和深浅copy

作者: 随便写写咯 | 来源:发表于2021-01-10 02:59 被阅读0次

    1. 条件

    条件可以是比较运算
    age = 18
    print(age > 16) # 条件判断后会得到一个布尔值True, 显示布尔值
    
    条件判断可以是True, False, 显示布尔值
    is_beautiful = True
    print(is_beautiful) >> True
    
    隐式布尔值:所有的值都可以当成条件去用
    0, None, 空为假(空字符串, 空列表, 空字典), 其余都为真
    

    2. 逻辑运算符

    逻辑运算: 根据逻辑运算的结果, 决定下一步操作
    
    逻辑运算符: 把多个条件连接在一起
    not, and, or
    优先级: not > and > or
    

    2.1 not

    not就是把紧跟其后的那个条件结果取反, not与紧跟其后的条件是一个不可分割的整体
    
    print(16 > 13) >> True
    print(not 16 > 13) >> False # 16 > 13是True, 通过not取反, 结果为False
    

    2.2 and

    and: 逻辑与, and用来连接多个条件, 每个条件都为True, 最终结果才为True
    
    print(10>3)
    print( True and False)
    print(True and 10 > 3 and 1 < 10)
    >>
    True
    False
    True
    

    2.3 or

    or: 逻辑或, or用来连接多个条件, 只要有一个为真, 结果为真, 所有结果为假, 结果才为假
    
    如果是单独就只是一串and连接,或者单独一串or连接, 按照从左到右的顺序依次运算即可, and遇到假则停止, or遇到真则停止
    如果是混用, 需要考虑优先级
    

    3. 成员运算符

    判断一个字符串是否存在于一个大字符串中
    
    print("admin" in "hello admin")  >> True
    print("x" in "hello admin")  >> False
    
    成员运算符在判断字典时,看的是key不是value
    
    print('x' in {"david":"xxx", "wang":"yyy", "admin":"zzzz"} ) 
    >> False
    
    not in: 不存在于xxx
    print("admin" not in "hello admin")
    >> False
    

    4. 身份运算符

    is: 判断的是id是否相等
    

    5. if条件判断

    语法1:
    if 条件: # 条件表达式只需要能返回一个bool值即可, 可以使比较运算, 逻辑运算, 显示bool或者隐式bool 
        代码1 #缩进四个空格
        代码2
        代码3
    
    语法2:
    if 条件:
        代码1
        代码2
        代码3
    else:
        代码1
        代码2
        代码3
    
    语法3:
    if 条件1:
        代码1
        代码2
        代码3
    elif 条件2:
        代码1
        代码2
        代码3
    elif 条件2:
        代码1
        代码2
        代码3
    
    语法4:
    if 条件1:
        代码1
        代码2
        代码3
    elif 条件2:
        代码1
        代码2
        代码3
    elif 条件2:
        代码1
        代码2
        代码3
    ...
    else:
        代码1
        代码2
        代码3
    

    6. 短路运算

    偷懒原则,偷懒到哪个位置,就把当前位置的值返回. 
    返回值可以是显示bool(True或者False), 也可以是隐式bool
    

    2. 深浅copy

    2.1 深浅copy引入

    执行list2= list1的结果: # 这不叫copy, 而是变量赋值, 把list1指向的内存地址, 和list2做绑定
    会在栈区中, 把list1的绑定的列表的内存地址, 绑定给list2, 此时list1和list2共同指向一块内存空间, 因此, 无论在list1还是在list2上对列表进行修改, 另一个列表都会受影响
    结果就是两个列表无法独立分开, 也就是写操作无法独立
    
    >>> list1 = ['dave','IT',[11,22]]
    >>> list2 = list1
    >>> list1[0] = 'jace'
    >>> print(list1)
    ['jace', 'IT', [11, 22]]
    >>> print(list2)
    ['jace', 'IT', [11, 22]]
    
    图片.png
    需求:
    1、拷贝一下原列表产生一个新的列表
    2、想让两个列表完全独立开,并且针对的是改操作的独立而不是读操作
    

    2.2 如何copy列表

    首先要知道, list2 = list1, 这不是copy, 只是变量的赋值
    

    2.2.1 浅copy

    list1=[
        'dave',
        'IT',
        [11,22]
    ]
    list3 = list1.copy()
    
    print(list3)
    ['dave', 'IT', [11, 22]]
    
    # 新的list3的列表的内存地址和list1不同, 说明.copy是浅copy, 会给新的列表开辟内存空间
    print(id(list1))
    print(id(list3))
    >>
    2695629813120  
    2695629626944
    
    # 两个列表内部的索引对应的内存地址相同, 说明, 虽然生成了新的列表内存空间, 但是列表内的索引和内存地址对应关系,还是不变的
    print(id(list1[0]),id(list1[1]),id(list1[2]))
    print(id(list3[0]),id(list3[1]),id(list3[2]))
    
    2323986184496 2323986184752 2323993114944
    2323986184496 2323986184752 2323993114944
    
    # 此时如果修改list1中不可变类型的值, 那么list3的值是不会跟着改变的
    # 因为修改不可变类型是会产生新的值, 开辟新的内存空间, 那么list1列表中的0号和1号索引就会指向新的内存地址, 而list3的0号和1号索引不受影响, 还是指向原来的'dave'和'IT'的内存地址
    
    list1=[
        'dave',
        'IT',
        [11,22]
    ]
    list3 = list1.copy()
    
    print(list1)  >> ['dave', 'IT', [11, 22]]
    list1[0] = 'DAVE'
    list1[1] = 'it'
    
    print(list1) >> ['DAVE', 'it', [11,22]]
    print(list3) >> ['dave', 'IT', [11, 22]]
    
    # 如果修改list1中的可变类型, 列表[11,22], 那么list3的值会跟着改变
    # 因为对于可变类型修改值, 并不会开辟新的内存空间, 而是在原有的空间基础上, 修改内部的原值
    list1=[
        'dave',
        'IT',
        [11,22]
    ]
    list3 = list1.copy()
    
    print(list1) >> ['dave', 'IT', [11, 22]]
    list1[2][0] = 33
    list1[2][1] = 44 
    print(list1) >> ['dave', 'IT', [33, 44]]
    print(list3) >> ['dave', 'IT', [33, 44]]
    

    总结:

    浅copy:是把原列表第一层的内存地址不加区分完全copy一份给新列表, 这时新的列表的变量名会指向新的内存地址, 但是这个内存地址里面的内容还是和源列表一样的.
    如果源列表中存的都是不可变类型, 比如整型, 字符串, 那么修改源列表的内容不会影响新的那个变量所绑定的列表. 因为对于不可变类型, 修改其变量赋值, 会开辟新的内容地址, 将源列表指向新的内存地址, 而后创建的列表还是指向没有修改的那些变量值.
    浅拷贝, 对于不可变类型的写操作, 没有影响, 新的列表的值不会随着源列表的值的改变而改变. 可以实现写操作的独立. 但是对于可变类型, 比如列表, 字典, 由于修改列表, 字典的内容不会开辟新的内存地址, 因此修改源列表的内容后, 新的列表的内容也会被修改, 无法实现写操作的独立. 浅拷贝就是完全把源列表的第一层内存地址完全复制给新的变量名
    对于不可变类型可以实现写操作独立, 但是对于可变类型, 无法实现写操作独立
    默认情况下, 所有的copy的都是浅拷贝
    
    图片.png

    2.2.2 深copy

    区分可变类型和不可变类型的copy机制, 要借助copy模块
    
    import copy
    list1=[
        'dave',
        'IT',
        [11,22]
    ]
    list3=copy.deepcopy(list1)
    print(id(list1)) >> 1744448240576 # 拷贝一定是得到一个新列表, 内存地址不同
    print(id(list3)) >> 1744448240832
    print(list3) >> ['dave', 'IT', [11, 22]]
    
    #        不可变        不可变        可变
    print(id(list1[0]),id(list1[1]),id(list1[2]))
    print(id(list3[0]),id(list3[1]),id(list3[2]))
    >>
    2646033824048 2646033824368 2646035904192
    2646033824048 2646033824368 2646035835328
    
    对于不可变类型, 和浅copy一样, 深拷贝是原封不动复制一份给新的列表, 内存地址是不变的, 这样读数据的时候还是读原先的内存地址, 节省空间
    但是对于可变类型, 深拷贝会产生一个新的内存空间, 里面放原有的值, 然后绑定给新的列表
    
    此时, 修改列表中的不可变类型, 那么不会影响新的列表, 这和浅copy一样
    如果修改列表中的可变类型, 那么也不会影响新的列表, 这就实现了列表复制后的写操作
    
    list1[0] = 'DAVE'
    list1[1] = 'it'
    list1[2][0] = 33
    list1[2][1] = 44
    print(list1) >> ['DAVE', 'it', [33, 44]] # list1完成修改
    print(list3) >> ['dave', 'IT', [11, 22]] # list3并没有受影响
    
    图片.png

    结论:

    如果需要复制出来一个新的列表, 并且实现两个列表写操作独立, 要用深copy
    

    相关文章

      网友评论

          本文标题:5. Python之条件判断和深浅copy

          本文链接:https://www.haomeiwen.com/subject/mmahaktx.html