• Python全栈开发【基础-09】深浅拷贝+while循环


    专栏介绍:

    本专栏为Python全栈开发系列文章,技术包括Python基础、函数、文件、面向对象、网络编程、并发编程、MySQL数据库、HTML、JavaScript、CSS、JQuery、bootstrap、WSGI、Django、Flask、后期运维、git使用、Linux运维、Python结合Shell结合场景开发自动化脚本等一系列文章. 从入门到实战。 文章内容来自博主学习笔记,修整发布。

    一、深浅copy


    首先深浅copy都是复制某个数据的意思,深浅拷贝指的就是在复制的时候对于值的内存空间地址有不同的一层区分,深拷贝对于复制可变类型的数据时会对内存当中值的可变不可变类型加以区分,而浅拷贝不会这么做,浅拷贝不会区分内存值的一个可变与不可变类型,只是复制第一层的内容。

    1.1 浅拷贝

    l1 = [111,222,333,[444,555,666]]
    l2 = l1.copy()
    
    print('这是copy后两个列表的内容'.center(50, '*'))
    print(l1)
    print(l2)
    
    print('这是copy后两个列表的内存id'.center(50, '*'))
    print(id(l1))
    print(id(l2))  # l2的复制后的列表是在内存地址当中新开辟了一个新的内存地址来存放列表
    
    print('这是copy后两个列表中的“值”的内存id'.center(50, '*'))
    print(id(l1[0]),id(l1[1]), id(l1[2]), id(l1[3]))
    print(id(l2[0]),id(l2[1]), id(l2[2]), id(l2[3]))
    
    
    print('修改l1列表当中index0-3的值'.center(50, '*'))
    l1[0] = 11111
    l1[1] = 22222
    l1[2] = 33333
    
    print(l1)
    print(l2)
    
    
    print('修改l1列表当中的可变类型'.center(50, '*'))
    l1[3][1] = 44444444
    print(l1)
    print(l2)
    
    
    
    [11111, 22222, 33333, [444, 555, 666]]
    [111, 222, 333, [444, 555, 666]]
    PS I:\python全栈开发> & D:/python/python3.7/python.exe i:/python全栈开发/python_develop/copy.py
    ******************这是copy后两个列表的内容******************
    [111, 222, 333, [444, 555, 666]]
    [111, 222, 333, [444, 555, 666]]
    *****************这是copy后两个列表的内存id*****************
    2532532970184
    2532533433352
    **************这是copy后两个列表中的“值”的内存id***************
    140710193885264 140710193888816 2532504520592 2532532970120
    140710193885264 140710193888816 2532504520592 2532532970120
    ****************修改l1列表当中index0-3的值****************
    [11111, 22222, 33333, [444, 555, 666]]
    [111, 222, 333, [444, 555, 666]]
    ******************修改l1列表当中的可变类型*******************
    [11111, 22222, 33333, [444, 44444444, 666]]
    [111, 222, 333, [444, 44444444, 666]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    使用列表的方法:.copy 默认为浅拷贝,那么浅拷贝也就说,对于列表当中的不可变类型会原封不动的拷贝,会创建一个新的内存地址用来存放[],那么其中的不可变类型的值与可变类型的值不会加以区分,会原封不动的拷贝过来,内存地址都会指向原来值的内存地址, 那么当原列表的不可变类型发生改变后,对于原列表来讲这是一个新的创造内存空间地址的操作,所以不会影响到新的l2,那么当l1的可变类型列表进行修改操作的时候,由于l2当中copy的可变类型不会加以区分,所以当l1发生改变之后,l2也会发生改变,那么这样的话浅拷贝是有问题的,如果只读的话没有问题,但是如果涉及到不同的内容需要写入列表操作的时候,就有问题。 深拷贝解决了这样的问题

    1.2 深拷贝 copy.deepcopy 方法

    import copy
    l1 = [111,222,333,[444,555,666]]
    l2 = copy.deepcopy(l1)
    
    print("深拷贝后l1与l2列表当中的数据".center(50, '*'))
    print(l1)
    print(l2)
    
    print("深拷贝后l1与l2列表当中的数据的内存地址".center(50, '*'))
    print(id(l1[0]),id(l1[1]),id(l1[2]),id(l1[3]))
    print(id(l2[0]),id(l2[1]),id(l2[2]),id(l2[3]))
    
    print("修改l1列表当中所有index的值,查看l2的变化,尤其是可变类型")
    l1[0] = 111111111111111
    l1[1] = 222222222222222
    l1[2] = 333333333333333
    l1[3][0] = 4444444444444
    l1[3][1] = 5555555555555
    l1[3][2] = 6666666666666
    
    print('这是修改后的l1的列表内容:{l11}'.format(l11=l1))
    print('这是修改后的l2的列表内容:{l22}'.format(l22=l2))
    
    
    *****************深拷贝后l1与l2列表当中的数据*****************
    [111, 222, 333, [444, 555, 666]]
    [111, 222, 333, [444, 555, 666]]
    **************深拷贝后l1与l2列表当中的数据的内存地址***************
    140710193885264 140710193888816 2225891002256 2225921619784
    140710193885264 140710193888816 2225891002256 2225921750856
    修改l1列表当中所有index的值,查看l2的变化,尤其是可变类型
    这是修改后的l1的列表内容:[111111111111111, 222222222222222, 333333333333333, [4444444444444, 5555555555555, 6666666666666]]
    这是修改后的l2的列表内容:[111, 222, 333, [444, 555, 666]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    通过以上代码发现深拷贝对于l1无论是可变类型还是不可变类型的修改操作不会影响到l2的深拷贝列表,表示着此时l2和l1列表是完全分离状态,深拷贝就是对于深拷贝对象的可变类型与不可变类型加以区分,对可变类型创造了新的内存地址防止修改后的影响

    二、流程控制的循环之while循环

    2.1 while循环的基本使用

    """
    while 条件:   # 条件成立运行代码块,条件不成立则退出
        代码1
        代码2
        代码3
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2 死循环的效率问题

    # 死循环1:
    while True:
        print('hello world')
    
    # 死循环2:
    while True:
        1 + 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:凡是死循环涉及到cpu计算操作的循环都是致命的,直接影响代码的效率问题,上面的print是一个io输出操作,但1 + 1无限计算是cpu的计算,这样会导致严重的效率问题。

    2.3 while循环退出的两种方式

    2.3.1 条件改为false

    name = "yanzan"
    password = "123"
    
    
    count = True
    while count:
        your_name = input('请您输入账号:')
        your_password = input('请您输入密码:')
    
        if your_name == name and your_password == password:
            print('登录成功!')
        else:
            print('登录失败!')
            count = False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3.2 while+break

    name = "yanzan"
    password = "123"
    
    while True:
        your_name = input('请您输入账号:')
        your_password = input('请您输入密码:')
    
        if your_name == name and your_password == password:
            print('登录成功!')
        else:
            print('登录失败!')
            break  # 直接跳出本次循环,简单粗暴
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.4 while循环的嵌套

    name = "yanzan"
    password = "123"
    
    while True:
        your_name = input('请您输入账号:')
        your_password = input('请您输入密码:')
    
        if your_name == name and your_password == password:
            print('登录成功!')
            while True:
                ml = input("请您输入命令:")
                if ml == 'q':
                    print('退出成功!!!')
                    break
                else:
                    print('{m}命令正在执行中.....'.format(m=ml))
            break
        else:
            print('登录失败!')
            break  # 直接跳出本次循环,简单粗暴
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.5 while+contiue

    跳出本次循环直接进入下一次的循环

    count = 0
    while count < 6:
        if count == 3:
            count += 1
            continue
        print(count)
        count += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.6 while+else

    name = "yanzan"
    password = "123"
    
    
    count = True
    while count:
        your_name = input('请您输入账号:')
        your_password = input('请您输入密码:')
    
        if your_name == name and your_password == password:
            print('登录成功!')
            while count:
                ml = input("请您输入命令:")
                if ml == 'q':
                    print('退出成功!!!')
                    count = False
                else:
                    print('{m}命令正在执行中.....'.format(m=ml))
            count = False
        else:
            print('登录失败!')
            count = False
    else:
        print("账号密码失败,此时打印的是while循环中的else,本循环正常退出,没有break打断")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    需要注意while+else的用法只是while循环正常退出的情况下,才会调用else,也就是说,不是被break打断while循环并且正常退出,就会运行else的内容。while循环可以理解为条件循环,根据条件循环的一种

    结束:

    在这里插入图片描述

  • 相关阅读:
    set和map的使用
    java计算机毕业设计学生课堂互动教学系统源码+mysql数据库+lw文档+系统+调试部署
    java计算机毕业设计双峰县在线房屋租售网站源代码+数据库+系统+lw文档
    R语言拟合ARIMA模型并使用拟合模型进行预测推理:使用forecast函数计算ARIMA模型未来值(包含时间点、预测值、两个置信区间)
    效率出图!9款最好用的矢量图软件推荐
    Github星标90K?京东架构师一篇讲明白百亿级并发系统架构设计
    java正则校验金额
    【MySQL】数据类型(一)
    【LeetCode】最大矩形(单调栈)
    svg常用属性及动画效果
  • 原文地址:https://blog.csdn.net/qq_39591494/article/details/126477940