面向对象-高级
一、多态
多态:指的是某种事物存在多种形态,例如:动物有:人 狗 猪
在程序中多态指的是,不同对象可以响应相同的方法,并可以有自己不同的实现方法
使用多态的好处:
1:增加了程序的灵活性 (以不变应万变,不论对象千变万化,使用者都是同一种形式去调用)
2:增加了程序的可扩展性(通过继承后再创建新的类)
实现多态:
接口 抽象 鸭子类型(拥有相似的属性和方法)都可以写出具备多态的代码
多态 鸭子类型 class Ji: def bark(self): print("gege") def spawm(self): print("下鸡蛋") class Duck: def bark(self): print("gaga") def spawm(self): print("下鸭蛋") class EI: def bark(self): print("eeee") def spawm(self): print("下鹅蛋") j=Ji() d=Duck() e=EI() # j.spawm() # d.spawm() # e.spawm() def manage(obj): # 管理同样属性的功能 obj.spawm() manage(j) manage(d) manage(e)
"pyhton中到处都有多态的现象" a=100 b="Gavin" c=0.12355 d={'name':"jack",'age':20} e=(12,45,54) print(type(a)) print(type(b)) print(type(c)) print(type(d)) print(type(e)) >>> <class 'int'> <class 'str'> <class 'float'> <class 'dict'> <class 'tuple'>
二、oop相关内置函数
1、isinstance(obj,cls):判断一个对象是否是某个类的对象 (判断类型的方法)
def add_num(a,b):
if isinstance(a,int) and isinstance(b.int): #判断是否是整型
return a+b
return None
a="100"
b=100
print(add_num(a,b))
# 判断是否是什么类型
2、issubclass(sub,super):判断一个类是否是另一个类的子类
class Animai: print("动物都能动...") class Pig(Animai): def eat(self): print("猪都吃猪食...") class Tree: def light(self): print("植物的光合作用") p=Pig() t=Tree() def manage(obj): # 定义一个管理系统 if issubclass(type(obj),obj): # 判断是不是子类的类 obj.eat() else: print("这不是同一类!") manage(Pig) manage(t) print(issubclass(Tree,object))
>>>> 动物都能动... Traceback (most recent call last): 这不是同一类!
三、类中的魔法函数:对象的显示相关函数
1:__str__ 会在对象被转换为字符串时,转换的结果就是这个函数的返回值
使用的场景:可以利用该函数来自定义,对象的是打印格式。
class Person: def __str__(self): #转换为字符串 print("run") return "abc" p=Person() print(p) >> run abc
class Person: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return "这是一个person对象 name:%s age:%s" %(self.name,self.age) pass # p=person() print(p) >>> 这是一个person对象 name:sore age:20 # 执行结果会覆盖——init——内置方法 执行打印的格式
2:__del__ 当手动删除对象时立马执行,或是程序运行结束时也会自动执行
使用的场景:当对象在使用过程中,打开了不属于解释器额资源,例如:文件 网络端口(网络编程)
import time class Person: def __init__(self,name,age): self.name=name self.age=age def __del__(self): print("del run ") p=person("reso",20) time.sleep(2) print("结束运行!")
__del__使用案例
# 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.read())
3:__call__ 执行时机:在调用对象时自动执行(即对象+括号)对象=类名()
#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}
4:__slots__ :该属性是一个类属性,用于优化对象内存占用
优化的原理:将原本不固定的属性数量,变得固定了这样的解释器就不会为这个对象创建名称空间,所以__dict__查看对象也没了,从而达到减少内存空间的效果
当类中出现了slots时 将导致这个类的对象无法在添加新的属性,开辟的内存空间地址
# slots的使用 class Person: __slots__ = ["name"] # 只固定开辟 name的内存空间 优化内存不浪费空间 def __init__(self,name): self.name = name print(self.__dict__) p = Person("jck") # print(sys.getsizeof(p)) # p.age = 20 # dict 没有了 print(p.__dict__)
四、属性的getattr setattr 和delattr getattribute
点语法.操作对象属性时自动触发
getattr:使用点语法访问属性的时候如果属性不存在时才执行 setattr:用点语法设置属性(修改/添加)时触发它的执行 delattr:使用点语法删除属性时触发
这几个函数反映了 python解释器时如何让实现 用点来访问属性的
getattribute: 该函数也是用来获取属性的:在获取属性时如果存在gqtattribute 则先执行该函数,如果没有拿到属性则继续调用getattr函数,如果拿到了则直接返回
class A: def __setattr__(self, key, value):# 设置 # print(key) # print(value) print("__setattr__") self.__dict__[key] = value def __delattr__(self, item): # 删除 print("__delattr__") print(item) self.__dict__.pop(item) pass def __getattr__(self, item): # 获取属性 print("__getattr__") return 1 def __getattribute__(self, item): print("__getattribute__") # return self.__dict__[item] return super().__getattribute__(item) a = A() a.name = "jack" print(a.name) del a.name print(a.name) print(a.xxx) a.name = "xxx" print(a.name) >>>> __setattr__ __getattribute__ __getattribute__ jack __delattr__ name
五、[ ] 的原理:
getitem setitem delitem
任何的符号都会被解释器解释成特殊的含义,例如,[ ] ()
getitem 当你用中括号去获取属性时 执行
setitem 当你用中括号去设置属性时 执行
delitem 当你用中括号去删除属性时 执行
案例:
class A: def __getitem__(self, item): print("__getitem__") return self.__dict__[item] def __setitem__(self, key, value): print("__setitem__") self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] print("__delitem__") a = A() # a.name = "jack" a["name"] = "jack" print(a["name"]) del a["name"] # print(a["name"]) >>> __setitem__ __getitem__ jack __delitem__
六、运算符重载:对象比较大小
当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用对应的处理函数,
当我们需要自定义对象的比较规则时,就可以在子类中覆盖 大于 等于 小于 等一系列的方法....
案列:
原本自定义对象无法直接使用大于、小于来进行比较,我们可自定义运算符来实现,让自定义对象也支持比较云算符
__gt__:大于比较、 def __It__:小于比较、 def__eq__:等于比较
class Student(object): def __init__(self,name,age,height): self.name=name self.age=age self.height=height def __gt__(self, other): # 比较大于 # print(self) print(other) return self.name>other.name def __eq__(self, other): # 比较等于 print(self) print(other) if self.name == other.name and self.age == other.age: return True return False def __lt__(self, other): # 比较小于 if self.age<other: return s=Student("reso",20,185) s1=Student("Jack",18,155) # print(s.name,s1.age) print(s>s1) print(s<s1) print(s==s1) >>>> True 20 NOne 原本类于类之间不能进行比较 通过函数“__gt__ __qe__ __lt__ ” 后可以进行比较
上述 程序中,other指的是另一个参与比较的对象: 大于和小于只要实现一个即可,
解释器会自动交换两个对象的位置即可
七、迭代器协议
迭代器是指具__iter__和__next__的对象
我们可以为对象增加这两个方法来让对象变成一个迭代器
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) >>>>1 3 5 7 9
实现让range(1,10)for 循环
八。上下文管理: __enter__
和__exit__
上下文:context
在Python中,上下文可以理解为是一个代码区间,一个范围,例如 witho open 打开的文件仅在这个上下文中有效
涉及的方法:
enter: 表示进入上下文 exit : 表示退出上下文
当执行with语句时 会先执行enter,当代码执行完毕后执行exit 或者代码遇到了异常会立即执行exit,并传入错误的信息
包含:错误的类型 错误的信息 错误的追踪信息
注意:
enter 函数应该返回对象自己
exit 函数 可以有返回值,是一个bool类型,用于表示异常是否被处理
仅在上下 文中出现异常有用
如果为True则意味着,异常以经被处理了
False,异常未被处理,程序将中断报错
本文来自博客园,作者:游走De提莫,转载请注明原文链接:https://www.cnblogs.com/Gaimo/p/11264065.html