前文课题

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

python 上下文管理器,多态,数据锁定与自省, Python 第1张

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

python 上下文管理器,多态,数据锁定与自省, Python 第2张

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

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

new 创建实例对象的时候

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

repr 调用repr方法的时候

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

上下文管理器

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

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

上下文管理器的概念:

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

上下文管理器的实现:

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

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

python 上下文管理器,多态,数据锁定与自省, Python 第3张

在本例中,运行没有抛出异常,就是因为使用了上下文管理器,异常可以在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的一部分(无论是函数,方法,还是数据成员。

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

访问:

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

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

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

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

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

python 上下文管理器,多态,数据锁定与自省, Python 第4张

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的话就会对所有对象属性进行限制,

 

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄