• python 上下文管理器,多态,数据锁定与自省,


    前文课题

    通过装饰器来实现单例模式

    装饰器单例.png

    通过类实现一个通用装饰器,皆可以装饰函数也可装饰类,即可有参也可无参

    类装饰器.png

    描述 new str repr call 分别会在什么时候被触发

    new 创建实例对象的时候

    str print实例对象的时候,str处理对象的时候,format处理对象的时候

    repr 调用repr方法的时候

    call 对象被调用的时候会触发

    上下文管理器

    思考一个问题,python中,with打开文件为什么会自动关闭,是怎么实现的

    with关键字后面跟着的事一个上下文管理对象

    上下文管理器的概念:

    上下文管理器是一个python对象,为操作提供了额外的上下文信息,这种额外的信息,在使用with语句初始化上下文,以及完成with块中的所有代码时,采用可调用的形式

    上下文管理器的实现:

    如果要自己实现上下文管理器,首先要知道上下文管理协议。

    简单来说,就是要在一个类里面实现enter和exit方法,这个类的实例就是一个上下文管理器。

    上下文.png

    在本例中,运行没有抛出异常,就是因为使用了上下文管理器,异常可以在exit进行捕获并且由编写者决定如何处理,是抛出还是在此就解决了,而在exit方法内部返回true(没有return则默认为false),相当于告诉python,这个异常已经捕获了,不需要再向外抛了。

    写exit函数时,需要注意,必须有三个参数:

    exc_type 异常类型,exc_val 异常值 , exc_tb 异常的错误栈信息,也就是异常回溯信息。

    而当代码没有异报异常的时候,三个参数都为None

    观察执行可以看出,在编写代码的时候可以将资源的连接或者获取放在 __enter__中,将资源的关闭卸载放在__exit__中。

    看一个实际应用: 需求 ,利用上下文管理器编写一个连接DB返回游标的类。

    # 实现一个操作mysql的上下文管理器,可以自动断开连接
     1 import pymysql
     2 class DB:
     3 
     4    def __init__(self, **data_conf):
     5       # 初始化db ,
     6       self.conn = pymysql.connect(**data_conf)
     7       self.cursor = self.con.cursor()
     8 
     9    def __enter__(self):
    10       # 将游标返回到上下文中
    11       return self.cursor
    12 
    13    def __exit__(self, exc_type, exc_val, exc_tb):
    14       self.cursor.close()
    15       self.conn.close()
    16 
    17 
    18 # 以元祖格式书写,直接强转成dict
    19 DB_conf = dict(
    20    host='localhost',
    21    user='root',
    22    password='123456',
    23    port=3306,
    24    charset='utf8'
    25 )
    26 print(type(DB_conf))
    27 print(DB_conf)
    28 # with 后面跟的是一个函数主题,也可以是自定义的类
    29 with DB(DB_conf) as cur:  # cur 作为enter方法返回的上下文句柄,是db的游标
    30    cur.execute('sql')
    31    print(cur.fetchone())
    32 
    33 # 描述slots属性的作用,并修改读取excel类中保存用例的类
    34 # 限制对象属性,指定指定的slots的属性
    35 # 节约内存
    36 class Case:
    37    __slots__ = ['case_id','title','url','data']
    38    def __int__(self):
    39       self.case_id = None
    40       self.title = None
    41       self.url = None
    42       self.data = None
    43 # 在进行实例化的时候 只能生成被slots进行指定的对象属性,且不会自动生成占用内存量大的__dict__
    44 # 使用场景主要是需要大量创建对象的时候,比如excel读取
     

    使用上下文管理器可以使代码更优雅。

    多态

    面向对象变成的三大特征,封装,继承,多态

    # 封装,将数据和方法放在一个类中构成封装
    # 继承 python中一个类可以继承于一个类也可以继承于多个类,被继承的类叫做父类或者基类
    # 继承的类叫做子类
    # 多态 指的事一类事物有多种形态,,噫个抽象类有多个子类(因而多态的概念依赖于继承
    # 不同的子类对象调用相同的方法,产生不同的执行结果,多态可以增加代码的灵活程度
    
    # 多态是建立在继承的基础上的
    # python中的多态是伪多态
    # python中函数的参数是没有类型限制的,传啥玩意儿都行
    

    实现多态的方法

    定义一个父类,实现某个方法

    定义多个子类,子类中重写父类的方法,每个子类方法实现不同的功能。

    假如定义了一个函数,需要一个base类型的对象的参数,那么调用函数的时候传入类型应当为base

    不同的子类对象,那么这个函数就会执行不同的功能,就是多态的体现

    多态的意义

    开放封闭原则

    对于一个变量,只需要知道它是base类型,无需确切的知道他的子类型就可以放心的调用run方法,调用方只管调用,不管内部细节

    当需要新增功能,只需要新增一个base的子类实现run方法,就可以在原来的基础上进行扩展

    就是开放封闭原则,对扩展开放,允许增加新的base子类,对修改封闭,不需要修改依赖base类型的run等函数

    鸭子类型

    概念, 并不要求严格的继承体系,关注的不是对象的类型本身,而是如何使用的,

    一个对象只要看起来像鸭子,走起路来像鸭子,就可以看做是鸭子

    鸭子类型的体现

    静态语言,对于静态语言 java c# 来讲,上面传入的对象必须是base类型或者它的子类,否则将无法调用run方法

               动态语言 对于动态语言python来讲,上面传入的并不一定要是base类型,也可以是其他类型,只要在内部实现一个run方法就行了,这就是鸭子类型的体现

    数据和自省

    私有属性定义

    单下划线开头的私有属性

    双下滑线开头的私有属性

    两者之间的区别

    首先,py中没有真正的私有化支持,但可用下划线得到伪私有,有一项大多数python代码都遵循的习惯,

    带有下划线前缀名称都应当被视为不可更改的api的一部分(无论是函数,方法,还是数据成员。

    它应该被视为实现细节,如有更改,不另行通知

    访问:

    类属性可以通过类和实例对象去访问,

    单下划线开头的私有属性也可以被类和实例访问

    双下划綫开头的私有属性,对外不可直接访问,为了保护这个变量,进行了改名

    改名的具体规则则是 在原有的基础上添加了 _类名 ,整体变为 _类名__属性名

    只有在使用新名字去访问的时候才可以访问到双下划綫修饰的变量

    私有属性.png

    dict 与 slots

     1 # __dict__
     2 # 类调用 ,返回类属性和方法的字典
     3 # 实例对象调用dict,返回实例中的数据行和方法的字典
     4 # 因为dict的存在会导致内存的消耗
     5 
     6 # 内置属性 __slots__
     7 # 默认情况下,类的实例有一个字典用于存储属性,这对于具有很少
     8 
     9 # 限制对象的属性
    10 #
    11 class Base(object):
    12    __slots__ = ['name']  # 指定类对象所能绑定的属性
    13 
    14 
    15 b = Base()
    16 # b.age =200  # 'Base' object has no attribute 'age'
    17 b.name = '阿迪'
    18 print(b.__dict__  )  #  'Base' object has no attribute '__dict__'
    19 # 定义了slots之后,就没有dict对象了,
    20 # slots可以做一个属性限制,,还有节约内存,定义了slots属性之后,该对象不会再自动
    21 # 生成 __dict__属性,
    22 
    23 # 那么为什么dict会占用内存呢?
    24 # 创建对象会自动生成dict,是一个字典,字典会首先划开一个比较大的内存空间
    25 # 加入说一个用例里面有很多属性 dict占用内存就会很多
    26 # __slots的话就会对所有对象属性进行限制,

     

  • 相关阅读:
    怎么在sublime里面显示编码格式
    鸟哥的Linux私房菜——第十七章:Linux 账号与身份管理
    反复
    鸟哥的Linux私房菜——第十六章:学习Shell Scripts
    鸟哥的Linux私房菜——第十五章:正规表示法
    鸟哥的Linux私房菜——第十四章:Bash Shell
    鸟哥的Linux私房菜——第十三章:Vim编译器
    Expression Blend实例中文教程(10)
    Expression Blend实例中文教程(9)
    Expression Blend实例中文教程(8)
  • 原文地址:https://www.cnblogs.com/addicated/p/13167351.html
Copyright © 2020-2023  润新知