day23多态
回顾
面向对象概率
面向对象是一种编程思想
组合、继承
封装:隐藏
新式类:继承Object的
覆盖:
接口:协议规范 只有一些方法的申明
抽象类
鸭子类型
子类访问父类
多态
定义
多个不同对象可以响应同一个方法,产生不同的结果。
就是多个对象有相同的使用方法。
强调
多态不是一种特殊的语法,而是一种状态,
好处:
对于使用者而言,大大的降低了使用难度
实现多态
接口 抽象类 鸭子类型 都可以写出具备多态的代码 最简单的就是鸭子类型
案列
"""
管理鸡鸭鹅
如何能够最方便的管理,就是我说同一句话 他们都能理解
即他们相同的方法
"""
class JI:
def bark(self):
print('gegege')
def spawn(self):
print('下鸡蛋')
class Duck:
def bark(self):
print('gagaga')
def spawn(self):
print('下鸭蛋')
class E:
def bark(self):
print('eee')
def spawn(self):
print('下鹅蛋')
j = JI()
y = Duck()
e = E()
j.spawn()
y.spawn()
e.spawn()
def mange(obj): # 可以用这个方法来操作
obj.bark()
mange(j)
mange(y)
mange(e)
#python中到处都有多态
# a = 10
# b = "10"
# c = [10]
#
# print(type(a))
# print(type(b))
# print(type(c))
oop相关内置函数
isinstance
判断一个对象是否是某个类的实例
参数1 要判断的对象
参数二 要判断的类型
# def add_num(a,b):
# return a+b
#
# add_num(100,10) #TypeError: must be str, not int
def add_num(a,b):
if type(a) == int and type(b) ==int:
return a+b
print(add_num(10,12)) #打印出22
def add_num(a,b):
if isinstance(a,int)and isinstance(b,int): #参数1 要判断的对象 参数2 要判断的类型
return a+b
return None
print(add_num("10",111))
issubclass
判断一个类是否是另一个类的子类
参数一 子类
参数二 父类
class Animal:
def eat(self):
print('动物得吃东西')
class Pig(Animal):
def eat(self):
print('🐖得吃🐖食')
class Tree:
def light(self):
print('植物光合作用')
pig = Pig()
t = Tree()
def manage(obj):
if issubclass(type(obj),Animal):
obj.eat()
else:
print("不是动物")
manage(pig)
manage(t)
print(issubclass(Tree,Animal)) # 第一个是子类,第二个是父类,打印出False
类中的魔法函数
_str_
__str__会在对象被转换为字符串时,转换的结果就是这个函数的返回值
使用场景: 我们可以利用该函数来自定义
# #
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
print('run')
return "这是一个person对象 name:%s age:%s" %(self.name,self.age)
# # # #
p = Person('jason',12)
print(p) #TypeError: __str__ returned non-string (type NoneType)
str(p) #run
_del_
执行时机 手动删除对象时立马执行 或是程序运行结束时也会自动执行
使用场景:当你
class FileTool:
'''该类用于简化文件的读写操作'''
def __init__(self,path):
self.file = open(path,'rt',encoding='utf-8')
self.a = 100
def read(self):
return self.file.read()
def __del__(self):
self.file.close()
tool = FileTool('a.txt')
print(tool.__del__())
call
class A:
def __call__(self, *args, **kwargs):
print('call run')
print(args)
print(kwargs)
a = A()
a(1,a = 100)
'''
打印出
call run
(1,)
{'a': 100}
'''
_slots_
该属性是一个类属性,用于优化对象内存占用
优化原理 将原本不固定的属性数量 变得固定了
这样的解释器就不会为这个对象创建名称空间了,所以__dict__也没有了
从而达到减少内存开销的效果
另外 当类中出现了slots时 将导致这个类的对象无法在添加新的属性
import sys
class Person:
__slots__ = ['name']
def __init__(self,name,):
self.name = name
p = Person('panyi')
print(sys.getsizeof(p)) # 优化内存
print(p.__dict__) # AttributeError: 'Person' object has no attribute '__dict__'
getattr\setattr delattr
getattr 用点访问属性的时候 如果属性不存在时执行
setattr 用点设置属性时
delattr 用del 对象.属性 删除属性时执行
这几个函数反映了 python解释器是如何实现用点来访问属性
getattribute 该函数也是用获取属性的
在获取属性时 如果存在getattribute 则先执行该函数 如果没有拿到属性则继续调用getattr函数 如果拿到了 则直接返回
中括号([])的实现原理
任何的符号 都会被解释器解释成特殊含义 ;列如.[]()
gettitem 当你用中括号去获取属性时执行
setitem 当你用中括号去设置属性时执行
delitem 当你用中括号去删除属性时执行
运算符重载
当我们在使用某个符号时,python解释器会为这个符号定义一个含义,同时调用对应的处理函数,当我们需要自定义对象的比较规则时,就可在子类中覆盖 大于 等于 等一系列方法....
案列
class Student:
def __init__(self,name,age,height,):
self.name = name
self.age = age
self.height = height
def __gt__(self, other):
print(other)
if self.height>=other.height:
return True
return False
stu1 = Student('jack',122,21)
stu2 = Student('rose',122,21)
print(stu1 >stu2)
#上述代码中,other指的是另一个参与比较的对象,
#大于和小于只要实现一个即可,符号如果不同 解释器会自动交换两个对象的位置
迭代器协议
迭代器
具有 __iter__和 __next__的对象
我们可以为对象增加这两个方法来让对象变成一个迭代器
案列 自定义range函数
class MyRange:
def __init__(self,start,end,step):
self.start = start
self.end = end
self.step = step
def __iter__(self):
return self
def __next__(self):
a = self.start
self.start += self.step
if a < self.end:
return a
else:
raise StopIteration
for i in MyRange(1,10,2):
print(i)
上下文管理
上下文 : context
这个概念指的是一段话的意义 要惨老当前的场景 即上下文
在python中 上下文可以理解为是一个代码区间 一个范围 例如 with open 打开的文件仅在这个上下文中生效
两个方法
enter
表示进入上下文(进去某个场景)
exit
表示退出上下文(退出某个场景)
当执行with语句时 会先执行enter,
当代码执行完毕后 执行exit 或者代码遇到了异常 会立即执行exit 并传入错误信息
包含错误的类型 错误的信息 错误的追踪信息
注意
enter 函数应该返回对象自己
exit函数 可以有返回值 是一个bool类型 用于表示异常是否被处理 仅在上下文中出现异常有用
如果True 则意味着 异常已经被处理了
False,异常未被处理 程序将中断报错