上下文管理深拷贝、浅拷贝

上下文管理器
  • 上下文管理的应用
    • 常用于一些资源操作,需要在资源的获取与释放的时候做相关的操作
  • 常见使用上下文管理的场景
    • 打开/关闭文件
    • 链接/关闭数据库
    • 网站的访问
  • 上下文管理器
    • 什么是上下文管理器
      • 实现了上下文协议的对象/函数即为上下文管理器
    • 上下文协议
      • 当我们需要创建一个上下文管理器类的时候,就需要实现__enter__和__exit__方法,这对方法就称为上下文管理协议(Context Manager Protocol),定义了一种运行时上下文环境。
  • 自定义一个上下文管理器类对象
    • 示例:
      • class Contextor(object):
        • def __enter__(self):
          • pass
        • def __exit__(self,*unused):
          • pass
  • 定义一个上下文管理器函数
    • 实现方法
      • 使用contextlib库来实现函数类型的上下文管理器
    • 示例:
      • @contextlib.contextmanager    
      • def func():       
        • handle = MongoClient('127.0.0.1', 27017)    
        • yield   handle
        • handle.close( )
    • 创建方法
      • 使用contextlib.contextmanager装饰上下文管理器函数    
      • 上下文管理器函数使用yield将代码段用到的对象返回    
      • 当上下文结束之后继续执行yield之后的工作
  • 上下文管理器的使用方法
    • with contextor [as var] : 
      • with_body
    • 备注:
      • contextor为上下文管理器,上下文管理器实现了上下文管理协议    
      • var变量存放上下文管理器返回的内容    
      • with_body为上下文过程中的处理代码
      • with 关键字用于在代码块运行前进入上下文环境   
        • 当使用上下文管理器对象的时候,上下文管理器就创建好了            
        • 与with搭配使用上下文管理器会加载调用__enter__方法,如果有as var从句,则将__enter__结果赋值给var    
        • 代码块执行结束触发调用__exit__    
        • 代码块执行异常触发调用__exit__,如果有返回False,这样异常会再代码块位置再触发一遍,程序会报错。
  • 常见的上下文管理器
    • 类文件对象
    • 创建数据库的句柄
    • 线程的threading.Lock()  线程锁
    • socket 创建的套接字对象
赋值、浅拷贝、深拷贝
  • 赋值操作
    • 赋值操作原理
      • python中的赋值操作实际上就是引用的赋值与传递
    • 示例:
      • a = [11,22]
      • b = a      
    • 示例解释:
      • 实际上就是将[11, 22]在内存中的地址赋给了a, 因此a将会指向[11. 22],而b = a操作,则将a中存储的值赋给了b,所以a、被指向了同一个数据的引用
  • 浅拷贝操作
    • 浅拷贝操作的原理
      • python中的浅拷贝使用copy模块的copy方法,拷贝时创建一个新的数据对象,并拷贝对象内部数据的引用
      • 如果拷贝的数据本身就是个不可变类型数据(比如元组),那么就只拷贝其引用
    • 示例:
    • 常见的浅拷贝的场景
      • 列表的切片
      • 字典的copy方法
      • list( )的内置函数
  • 深拷贝操作
    • 深拷贝操作的原理
      • 创建一个新的数据对象,对每个包含的数据进行递归的拷贝操作,当检测到拷贝的引用指向的是一个不可修改的对象时,那么拷贝对象的引用
      • 深拷贝是对数据对象的完全拷贝,当被拷贝的数据是可变类型将会复制其结构,深拷贝之后得到的结果与原数据没有任何的联系,任何对原数据的修改都不会影响深拷贝之后的数据
    • 示例:
  • 拷贝的特殊情况
    • 拷贝元组数据
      • 当元组中不含有可变类型数据的时候
        • copy.copy和copy.deepcopy的到的结果都是对拷贝内容的引用            
        • eg:  a = (11,22)        
      • 当元组中含有可变类型数据
        • copy.copy拷贝的结果是引用
        • copy.deepcopy是深拷贝           
        • eg:  a = [11,22]  b = [33,44]
        •         c  =  (a,b)
    • 函数传参拷贝数据
      • 函数传参的方法
        • def func(*args, **kwargs)
          • body
      • 函数传参的时候需要注意
        • 默认传参只是会传递引用                       
        • 当参数为可变数据时(列表,字典等),如果参数只使用而不修改,可直接传参,如果涉及到修改,函数内的修改会影响函数外的使用            
        • 如果想避免第二种情况,可以传递深拷贝数据来避免函数修改原来数据            

刘小恺(Kyle) wechat
如有疑问可联系博主