Python进阶-数据拷贝问题

Python进阶系列
Python进阶-网络编程-01
Python进阶-网络编程-02
Python进阶-网络编程-03
Python进阶-多任务编程-01
Python进阶-多任务编程-02
Python进阶-多任务编程-03
Python进阶-正则表达式
Python进阶-数据库编程-01
Python进阶-数据库编程-02
Python进阶-数据库编程-03
Python进阶-数据库编程-04
Python进阶-数据拷贝问题
Python进阶-模块导入问题
Python进阶-miniWeb框架

14.1. 带参数的装饰器

  • 作用:向装饰器内部传递参数

  • 格式

    def test(path):
        def function_out(func):
            def function_in():
                print("开始验证")
                func()
            return function_in
        return function_out
    
  • 使用

      @test("login.py")
      def login():
          print("开始登录")
        
      @test("register.py")
      def register():
          print("开始注册")
        
          login()
    

    在这里插入图片描述

  • 代参装饰器的典型写法

    def mylog(type):
        def decorator(func):
            def infunc(*args,**kwargs):
                if type == "文件":
                    print("文件中: 日志目录")
                else:
                    print("控制台: 日志记录")
                return func(*args,**kwargs)
            return infunc
        return decorator
    
    @mylog("文件")
    def fun2(a,b):
        print("使用功能2",a,b)
    
    if __name__ == '__main__':
        fun2(100,200)
    

    在这里插入图片描述


14.2. 多重装饰器

  • 多重装饰器:给一个函数进行多次装饰
  • 装饰原则:就近原则(靠近待装饰函数的先装饰,随后一层一层装饰)

14.3. 类装饰器

  • 作用:使用一个类为一个函数装饰, 主要思路就是返回一个增加了新功能的函数对象,只不过这个函数对象是一个类的实例对象。由于装饰器是可调用对象,所以必须在类里面实现__call__方法,这样由类生成的各种实例加上()就可以运行。

  • 类的书写

    • 必须有两个方法
      • __init__,必须接收装饰器传递的参数 func

      • __call__,建立装饰器时自动调用

        @类名
        带装饰的函数
        
        class Test(object):
              def __init__(self,func):
                  self.func = func
        
        def __call__(self, *args, **kwargs):
              print("call")
              self.func()
        
  • 不带参数的类装饰器

      import time
        
        
        class Decorator:
            def __init__(self, func):
                self.func = func
        
            def defer_time(self):
                time.sleep(5)
                print("延时结束了")
        
            def __call__(self, *args, **kwargs):
                self.defer_time()
                self.func()
        
        
        @Decorator
        def f1():
            print("延时之后我才开始执行")
        
        f1()
    

    在这里插入图片描述

  • 带参数的类装饰器

    import time
    
    
    class Decorator:
        def __init__(self, func):
            self.func = func
    
        def defer_time(self, time_sec):
            time.sleep(time_sec)
            print(f"{time_sec}s延时结束了")
    
        def __call__(self, time):
            self.defer_time(time)
            self.func()
    
    
    @Decorator
    def f1():
        print("延时之后我才开始执行")
    
    
    f1(5)
    

    在这里插入图片描述

  • 对象名() 调用对象__call__()


14.4. GIL锁引入

  • 监控资源的竞争情况htop
  • 资源的消耗情况
    • 单进程 1核
    • 多进程 多核
    • 多线程 多核但是很低 GIL锁的问题

14.5. GIL概念及影响

  • GIL 全局解释器锁
  • GIL跟python语言没有关系,python底层解释器Cpython的问题
  • GIL锁释放的情况
    • 线程执行完毕释放
    • I/O阻塞的时候释放
    • python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)

14.6. GIL解决方案

  • 解决方案
    1. 更换解释器 Jpython pypy
    2. 用进程替换线程 进程会占用更多的系统资源子线程
    3. 用c语言实现 (test.c -> libtest.so -> python加载)

14.7. python中可变和不可变

  • 可变类型:创建后可以继续修改对象的内容

    • 包含:字典、列表
  • 不可变类型:一旦创建就不可修改的对象

    • 包含:数字、字符串、元组

    • 当内容发生修改,计算机重新分配一块内存空间


14.8. 简单可变类型拷贝

  • 深拷贝:

    1. 会产生新的空间
    2. 能够保持各自的独立性
  1. 如果拷贝的对象,子对象也会拷贝(产生新的空间)
  • 代码实例:

    # 定义list1列表
    list1 = [1,2,3]
    print("list1 =",list1,id(list1))
    
    # 定义list2列表,深拷贝list1
    list2 = copy.deepcopy(list1)
    print("list2 =",list2,id(list2))
    
    # 改变list2的数据
    list2.append(7)
    print("list2 =",list2,id(list2))
    
    # list1不发生变化,能够保证数据的独立性
    print("list1 =",list1,id(list1))
    

在这里插入图片描述

  • 浅拷贝:

    • 会产生新的空间
  • 能够保持各自的独立性

    • 如果拷贝的对象,子对象也会拷贝(产生新的空间)

    • 代码实例:

      # 定义list1列表
      list1 = [1,2,3]
      print("list1 =",list1,id(list1))
      # 定义list2列表,深拷贝list1
      list2 = copy.copy(list1)
      print("list2 =",list2,id(list2))
      # 改变list2的数据
      list2.append(7)
      print("list2 =",list2,id(list2))
      # list1不发生变化,能够保证数据的独立性
      print("list1 =",list1,id(list1))
      

      在这里插入图片描述

  • 简单可变类型的拷贝总结:

    简单可变类型的数据不管深拷贝还是浅拷贝,都会产生新的空间,而且保持各自的独立性


14.9. 复杂可变类型拷贝

  • 深拷贝:拷贝的顶层对象和对象的子对象,子对象会产生新的内存空间

    • 代码实例:

      A = [1, 2, 3]
      B = [4, 5, 6]
      C = [A, B]
      
      
      print("A = ", A, id(A))
      print("C = ", C, id(C))
      
      D = copy.deepcopy(C)
      print("D = ", D, id(D))
      
      print("D[0] =",id(D[0]),"   C[0] =",id(C[0]),"   A =",id(A))
      
      A[0] = 10
      print("D[0] =", D[0], id(D[0]))
      print("D = ", D, id(D))
      print("A = ", A, id(A))
      

      在这里插入图片描述

  • 浅拷贝:拷贝的是顶层对象的值,子对象不会拷贝(只是引用子对象)

    • 代码实例

          A = [1,2,3]
          B = [4,5,6]
          C = [A,B]
      
      
          print("A = ",A,id(A))
          print("B = ",B,id(B))
          print("C = ",C,id(C))
          print("C[0] =",C[0],id(C[0]))
      
          D = copy.copy(C)
          print("D = ",D,id(D))
          print("D[0] =",D[0],id(D[0]))
      
          A[0] = 10
          print("D[0] =",D[0],id(D[0]))
          print("D = ",D,id(D))
      

      在这里插入图片描述


14.10. 简单不可变类型拷贝

  • 深拷贝:副本和源指向同一个空间

    • 代码实例

      tuple1 = (1, 2, 3)
      print("tuple1= ", tuple1, id(tuple1))
      
      tuple2 = copy.deepcopy(tuple1)
      print("tuple2= ", tuple2, id(tuple2))
      

      在这里插入图片描述

  • 浅拷贝:副本和源指向同一个空间

    • 代码实例

      tuple1 = (1,2,3)
      print("tuple1 =",tuple1,id(tuple1))
      
      tuple2 = copy.copy(tuple1)
      print("tuple2 =",tuple2,id(tuple2))
      

      在这里插入图片描述


14.11. 复杂不可变类型拷贝

  • 深拷贝:看数据具体是可变还是不可变的,如果数据是可变的,会产生新的空间,保持数据的独立性。如果是不可变类型,不会产生新的空间,无法保证数据的独立性

    • 代码实例

      A = [1, 2, 3]
      B = [4, 5, 6]
      
      C = (A, B)
      print("C =", C, id(C))
      
      D = copy.deepcopy(C)
      print("D =", D, id(D))
      
      D[0][0]=10
      print("C =", C, id(C))
      print("D =", D, id(D))
      

      在这里插入图片描述

  • 浅拷贝:直接引用,不会产生新的空间,无法保证数据的独立性

    • 代码实例

      A = [1,2,3]
      B = [4,5,6]
      
      C = (A,B)
      print("C =",C,id(C))
      
      D = copy.copy(C)
      print("D =",D,id(D))
      

      在这里插入图片描述


14.12. 切片拷贝、字典拷贝

  • 切片拷贝:浅拷贝(如果是简单可变类型,底层会产生新的空间)

    • 代码实例1

       list1 = [1, 2, 3, 4, 5, 6, 7]
       print("list1 =", list1, id(list1))
      
       list2 = list1[:]
       print("list2 =", list2, id(list2))
      

      在这里插入图片描述

    • 代码实例2

      A = [1,2,3]
      B = [4,5,6]
      
      C = (A,B)
      print("C = ",C,id(C))
      D = C[:]
      print("D = ",D,id(D))
      

      在这里插入图片描述

  • 字典拷贝:浅拷贝

    • 代码实例

      dict1 = {"age":[1,2]}
      print("dict1 =",dict1,id(dict1))
      
      dict2 = dict1.copy()
      print("dict2 =",dict2,id(dict2))
      
      dict1['age'][0] = 100
      print("dict1 =",dict1,id(dict1))
      print("dict2 =",dict2,id(dict2))
      

      在这里插入图片描述


14.13. 拷贝总结

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值