Python学习笔记【第十一篇】:Python面向对象高级
程序员文章站
2022-03-25 22:04:57
isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 issubclass(sub, super)检查sub类是否是 super 类的派生类 反射 python面向对象中的反射:通过字符串的形 ......
isinstance(obj,cls)和issubclass(sub,super)
1 class Person(object): 2 def __init__(self, name, age, sex, nationality): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 self.nationality = nationality 7 8 def say(self): 9 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 10 11 def __getattr__(self, item): 12 print("当实例获取属性不存在的时候会执行__getattr__方法") 13 14 def __getattribute__(self, item): 15 print("实例获取属性,不管实例dict属性字典里又没有都会执行__getattribute__方法") 16 17 18 class Chinese(Person): 19 pass 20 21 22 if __name__ == "__main__": 23 p1 = Person("里斯", 78, '男', "美国") 24 # p1 实例是否是Person类的一个实例 25 print(isinstance(p1, Person)) 26 # issubclass(sub, super)检查sub类是否是 super 类的派生类 27 print(issubclass(Chinese, Person))
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
issubclass(sub, super)检查sub类是否是 super 类的派生类
反射
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
hasattr(obj,"属性"):# obj.属性是否存在
getattr(obj,"属性"):# 获取 obj.属性 如果不存在就报错
getattr(obj,"属性","默认值"):# 获取 obj.属性 如果不存在不会报错,并且返回默认的
setattr(obj,"属性"):# 设置属性
delattr(obj,"属性"):# 删除属性
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 7 class Person(object): 8 name = "hah" 9 10 def __init__(self, name, age, sex, nationality): 11 self.name = name 12 self.age = age 13 self._sex = sex 14 self.__nationality = nationality 15 16 def say(self): 17 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s" % (self.name, self.age, self._sex, self.__nationality)) 18 19 20 class Chinese(Person): 21 pass 22 23 24 if __name__ == "__main__": 25 print("\r\n ==============对象的反射============ \r\n") 26 p1 = Person("张三", 18, '男', "中国") 27 p1.say() 28 # 获取 p1 对象里name的值 29 print(getattr(p1, "name")) 30 31 # 判断p1对象里又没有addr属性 32 print(hasattr(p1, "addr")) 33 34 # 设置p1 对象addrs属性并且赋值 35 setattr(p1, "addrs", "四川达州") 36 print(getattr(p1, "addrs")) 37 38 # 删除p1对象addrs属性 39 delattr(p1, "addrs") 40 print(hasattr(p1, "addrs")) 41 42 print("\r\n ==============类的反射(类本质上也是对象)============ \r\n") 43 print(hasattr(Person, "addrs")) 44 print(getattr(Person, "name", "没有这个属性")) 45 setattr(Person, "addrs", "类地址") 46 print(getattr(Person, "addrs")) 47 delattr(Person, "name") 48 print(hasattr(Person, "name"))
importlib---动态导入模块
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 from Python基础.myImport import chufa 7 import importlib 8 9 if __name__ == "__main__": 10 # 第一种导入调用 11 # print(chufa(1000,50)) 12 13 # 第二种:动态导入模块 14 # m1 = __import__("myImport") 15 # print(m1) 16 # # 调用模块里的方法 17 # print(m1.chufa(10,2)) 18 19 # # 第三中:动态导入模块 20 # m2 = importlib.import_module("myImport") 21 # print(m2) 22 # print(m2.chufa(4,2)) 23 m3 = importlib.import_module("modular.sendMsg") 24 print(m3) 25 print(m3.SendMsage())
__setattr__,__delattr__,__getattr__
__getattr__:不存在的时候出发 __setattr__:设置属性的值的时候出发 __delattr__:删除属性的时候出发
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 """ 7 __getattr__:不存在的时候出发 8 __setattr__:设置属性的值的时候出发 9 __delattr__:删除属性的时候出发 10 11 """ 12 13 14 class Person(object): 15 def __init__(self, name, age, sex, nationality): 16 self.name = name 17 self.age = age 18 self.sex = sex 19 self.nationality = nationality 20 21 def say(self): 22 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 23 24 def __getattr__(self, item): 25 print("执行了__getattr__") 26 27 def __setattr__(self, key, value): 28 print("执行了__setattr__") 29 # 实际上就是操作属性字典 30 self.__dict__[key] = value 31 32 def __delattr__(self, item): 33 print("执行了__delattr__") 34 self.__dict__.pop(item) 35 36 37 class Chinese(Person): 38 pass 39 40 41 class American(Person): 42 pass 43 44 45 class Korean(Person): 46 pass 47 48 49 class Japanese(Person): 50 pass 51 52 53 if __name__ == "__main__": 54 pass 55 # # 因为在类中重写了设置属性的方法,然而代码里并没有正在设置上,所以调用say会报错 56 # p1 = Person("张三",18,'男',"中国") 57 # p1.say() 58 59 # 修改后在执行 60 p1 = Person("张三", 18, '男', "中国") 61 p1.say() 62 del p1.name 63 print(hasattr(p1, "name"))
__getattr__例子:
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 import time 7 8 9 class FileHelper(object): 10 def __init__(self, filepath, model="r", encoding='utf-8'): 11 self.file = open(filepath, mode=model, encoding=encoding) 12 13 def __getattr__(self, item): 14 # item 是字符串类型 15 # 通过getattr()获取 self.file 中的方法 16 return getattr(self.file, item) 17 18 def write(self, line): 19 # 在每次写入的内容前面加上时间 20 t = time.strftime("%Y-%m-%d %X") 21 self.file.write('%s %s' % (t, line + "\r\n")) 22 23 24 if __name__ == "__main__": 25 f1 = FileHelper("../files/Log/logger.log", 'w', encoding='utf-8') 26 f1.write("锄禾日当午") 27 f1.write("汗滴禾下土") 28 f1.write("谁知盘中餐") 29 f1.write("粒粒皆辛苦") 30 31 f1 = FileHelper("../files/Log/logger.log", 'r', encoding='utf-8') 32 # f1.read() 首先在f1实例中的__dict__数据字典中去找read方法,如果没有就去FileHelper类中的__dict__数据字典中找,如果还是没有 33 # 就报错,如果在FileHelper中重写的__getattr__方法,就执行该方法。所以在该方法中通过self.file属性中去找,self.file就是系统的open对象。 34 content = f1.read() 35 print(content)
__setitem__,__getitem,__delitem__
1 class Chinese(Person): 2 3 def __getitem__(self, item): 4 print("执行了__getitem__") 5 6 def __setitem__(self, key, value): 7 print("执行了__setitem__") 8 9 def __delitem__(self, key): 10 print("执行了__delitem__") 11 c1 = Chinese("李四",14,"女","中国") 12 c1["addrs"] = "四川成都" 13 c1['addrs'] 14 del c1["addrs"]
__getattribute__
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 class Person(object): 7 def __init__(self, name, age, sex, nationality): 8 self.name = name 9 self.age = age 10 self.sex = sex 11 self.nationality = nationality 12 13 def say(self): 14 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 15 16 def __getattr__(self, item): 17 print("当实例获取属性不存在的时候会执行__getattr__方法") 18 19 def __getattribute__(self, item): 20 print("实例获取属性,不管实例dict属性字典里又没有都会执行__getattribute__方法") 21 22 23 24 if __name__ == "__main__": 25 p1 = Person("里斯", 78, '男', "美国") 26 # p1 实例是否是Person类的一个实例 27 print(isinstance(p1, Person)) 28 # issubclass(sub, super)检查sub类是否是 super 类的派生类 29 print(issubclass(Chinese, Person)) 30 31 # getattribute方法 32 # addrs不存在与p1的dict属性字典里,所以会执行getattr方法 33 p1.addrs 34 p1.name 35 """ 36 当实例中同时具有__getattr__和__getattribute__方法时候,都只会执行__getattribute__方法,如果__getattribute__方法里有 37 抛出AttributeError异常,就会出发 __getattr__方法。 38 39 """
总结
obj点的方式操作属性时候出发
__getattr__:不存在的时候出发
__setattr__:设置属性的值的时候出发
__delattr__:删除属性的时候出发
obj['属性']的的方式操作属性的时候出发
__getitem__:不存在的时候出发
__setitem__:设置属性的值的时候出发
__delitem__:删除属性的时候出发
def __get__():
pass
def __set__():
pass
def __del__():
pass
描述的就是一个新式类,这个类至少实现上述三个方法中的一个
改变对象的字符串显示__str__,__repr__
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 # 改变对象的字符串显示__str__,__repr__ 7 8 class Person(object): 9 def __init__(self, name, age, sex, nationality): 10 self.name = name 11 self.age = age 12 self.sex = sex 13 self.nationality = nationality 14 15 def say(self): 16 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 17 18 def __str__(self): 19 return '重写str方法,默认就返回我啦!!!' 20 21 def __repr__(self): 22 return '通过解释器执行后返回的' 23 24 25 if __name__ == "__main__": 26 # 实例中没有__str__函数,打印实例 地址,加了之后,打印重写后返回的内容。 27 p1 = Person("小村伊朗", 78, '妖', '小岛') 28 print(p1)
__next__和__iter__实现迭代器协议
高效的求斐波拉契数列方法
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 class FeiBoLa(object): 7 def __init__(self): 8 self.__a = 1 9 self.__b = 1 10 11 def __iter__(self): 12 return self 13 14 def __next__(self): 15 self.__a, self.__b = self.__b, self.__a + self.__b 16 return self.__a 17 18 19 if __name__ == "__main__": 20 f = FeiBoLa() 21 print(f.__next__()) 22 print(f.__next__()) 23 print(f.__next__()) 24 print(f.__next__()) 25 print(f.__next__())
__enter__和__exit__组成with语法
with MyOpen('a.txt') as f: print(f) print('执行代码块')
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 """ 6 7 8 案例: 9 with MyOpen('a.txt','r',encoding='utf-8') as f: 10 pass 11 12 13 __enter__(): MyOpen('a.txt','r',encoding='utf-8') 会触发 MyOpen类中的__enter__方法 14 __exit__():执行完代码块中的代码后出发 __exit__方法。 15 16 """ 17 18 19 class MyOpen(object): 20 def __init__(self, path, model='r', encoding='utf-8'): 21 self.path = path 22 self.model = model 23 self.encoding = encoding 24 25 def __enter__(self): 26 print('执行了enter方法.....') 27 28 def __exit__(self, exc_type, exc_val, exc_tb): 29 # 如果发生异常 对应三个值的说明 30 # exc_type:异常类, exc_val:异常值, exc_tb:异常追踪信息 31 print('执行了exit方法......') 32 print(exc_type) 33 print(exc_val) 34 print(exc_tb) 35 return False 36 37 38 if __name__ == "__main__": 39 with MyOpen('a.txt') as f: 40 print(f) 41 print('执行代码块')
案例:
描述符类装饰器给类动态添加属性
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 # 类属性描述 7 class AttrDesc: 8 9 def __init__(self, attr_name, attr_type): 10 self.attr_name = attr_name 11 self.attr_type = attr_type 12 13 def __get__(self, instance, owner): 14 return instance.__dict__[self.attr_name] 15 16 def __set__(self, instance, value): 17 if not isinstance(value, self.attr_type): 18 raise TypeError("%s值的类型不是:%s" % (self.attr_name, self.attr_type)) 19 instance.__dict__[self.attr_name] = value 20 21 def __delete__(self, instance): 22 return instance.__dict__.pop(self.attr_name) 23 24 25 # 限制类属性类型装饰器 26 def add_attr(**kwargs): 27 def add(obj): 28 for key, val in kwargs.items(): 29 setattr(obj, key, AttrDesc(key, val)) 30 31 return obj 32 33 return add 34 35 36 @add_attr(height=float, weigt=float, name=str) 37 class Person(object): 38 def __init__(self, name, age, sex, nationality): 39 self.name = name 40 self.age = age 41 self.sex = sex 42 self.nationality = nationality 43 44 def say(self): 45 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 46 47 48 if __name__ == "__main__": 49 p1 = Person('小明', 12, '男', '中国') 50 p1.height = 2.19 51 print(Person.__dict__)
案例:自定义property
可以让一个方法 看起来像一个属性,使用的时候对象点出来即可
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 class LazyPropery: 7 def __init__(self, func): 8 self.func = func 9 10 def __get__(self, instance, owner): 11 print(instance) 12 print(owner) 13 if instance is None: 14 return self 15 return self.func(instance) 16 17 18 class Person(object): 19 def __init__(self, name, age, sex, nationality): 20 self.name = name 21 self.age = age 22 self.sex = sex 23 self.nationality = nationality 24 25 # 标记上@property 变为静态属性,这样就可以通过实例名点方法名调用。 26 @property 27 def say(self): 28 print("大家好我叫:%s 今年%d岁了,我是一名%s生来自%s。" % (self.name, self.age, self.sex, self.nationality)) 29 30 31 class Chinese(Person): 32 33 @LazyPropery 34 def run(self): 35 print('run') 36 return '我是%s' % self.name 37 38 39 if __name__ == "__main__": 40 print("\r\n======系统内置property=====\r\n") 41 p1 = Person('王二小', 12, '女', '中国') 42 p1.say 43 print("\r\n======自定义的property=====\r\n") 44 c1 = Chinese('王二', 15, '女', '中国') 45 print(c1.run)
工厂模式案例:
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 ''' 6 在父类中定义,在子类中实现 ========工厂模式 7 ''' 8 9 10 # 店铺类 11 class Store(object): 12 def select_car(self): 13 pass 14 15 def Order(self, car_type): 16 return self.select_car(car_type) 17 18 19 # 宝马4S店 20 class BMStore(Store): 21 def select_car(self, car_type): 22 return BMFactory().select_car_by_type(car_type) 23 24 25 # 桑塔纳4S店 26 class STNStore(Store): 27 def select_car(self, car_type): 28 return STNFactory().select_car_by_type(car_type) 29 30 31 # 雪佛兰4S店 32 class XFLStore(Store): 33 def select_car(self, car_type): 34 return XFLFactory().select_car_by_type(car_type) 35 36 37 # 宝马工厂 38 class BMFactory(object): 39 def select_car_by_type(self, car_type): 40 if car_type == "宝马X": return BaoMaX() 41 if car_type == "宝马XX": return BaoMaXX() 42 if car_type == "宝马XXX": return BaoMaXXX() 43 44 45 # 桑塔纳工厂 46 class STNFactory(object): 47 def select_car_by_type(self, car_type): 48 if car_type == "桑塔纳Q": return SangTaNaQ() 49 if car_type == "桑塔纳QQ": return SangTaNaQQ() 50 51 52 # 雪佛兰工厂 53 class XFLFactory(object): 54 def select_car_by_type(self, car_type): 55 if car_type == "雪佛兰T": return XueFuLanT() 56 if car_type == "雪佛兰TT": return XueFuLanTT() 57 58 59 # 整个车类 60 class Car(object): 61 def move(self): 62 print("车在移动......") 63 64 def music(self): 65 print("车里再放音乐....") 66 67 def stop(self): 68 print("车停下了.......") 69 70 71 # 宝马车类 72 class BaoMa(Car): 73 pass 74 75 76 class BaoMaX(BaoMa): 77 pass 78 79 80 class BaoMaXX(BaoMa): 81 pass 82 83 84 class BaoMaXXX(BaoMa): 85 pass 86 87 88 # 桑塔纳车类 89 class SangTaNa(Car): 90 pass 91 92 93 class SangTaNaQ(SangTaNa): 94 pass 95 96 97 class SangTaNaQQ(SangTaNa): 98 pass 99 100 101 # 雪佛兰车类 102 class XueFuLan(Car): 103 pass 104 105 106 class XueFuLanT(XueFuLan): 107 pass 108 109 110 class XueFuLanTT(XueFuLan): 111 pass 112 113 114 stor = BMStore() 115 s = stor.Order("宝马XX") 116 s.move() 117 s.music() 118 s.stop()
简单工厂模式案例:
1 # -*- coding: utf-8 -*- 2 3 # 声明字符编码 4 # coding:utf-8 5 6 7 #<region 简单工厂模式> 8 9 # 店铺类 10 class CarStore(object): 11 def __init__(self): 12 self.factory = Factory() 13 def Order(self,car_type): 14 return self.factory.select_car_by_type(car_type) 15 16 17 # # 店铺类 18 # class CarStore(object): 19 # def Order(self,car_type): 20 # return select_car_by_type(car_type) 21 22 23 24 class Factory(object): 25 def select_car_by_type(self,car_type): 26 if car_type =="宝马":return BaoMa() 27 if car_type == "桑塔纳":return SangTaNa() 28 if car_type == "雪佛兰":return XueFuLan() 29 30 # # 函数(达到了解耦性) 31 # def select_car_by_type(car_type): 32 # if car_type =="宝马":return BaoMa() 33 # if car_type == "桑塔纳":return SangTaNa() 34 # if car_type == "雪佛兰":return XueFuLan() 35 36 # 整个车类 37 class Car(object): 38 def move(self): 39 print("车在移动......") 40 def music(self): 41 print("车里再放音乐....") 42 def stop(self): 43 print("车停下了.......") 44 45 46 # 宝马车类 47 class BaoMa(Car): 48 pass 49 # 桑塔纳车类 50 class SangTaNa(Car): 51 pass 52 # 雪佛兰车类 53 class XueFuLan(Car): 54 pass 55 56 57 58 59 stor = CarStore() 60 s = stor.Order("宝马") 61 s.move() 62 s.music() 63 s.stop() 64 65 #<endregion>
上一篇: 2018年3月至4月小结
下一篇: Python入门(案例)