day24:多态&魔术方法__new__&单态模式
目录1.多态 2.__new__魔术方法 2.1?关于魔术方法__new__ 2.2?基本语法 2.3?__new__ 触发时机快于构造方法 2.4?__new__ 和 __init__ 参数一一对应 2.5?关于__new__的注意点 3.单态模式 4.连贯操作 5.小人射击项目 多态什么是多态?不同的子类对象,调用相同的父类方法,产生不同的执行结果 多态的关键字:继承和改写 下面的例子完美展示了python的多态: # 定义Soldier类,让空军陆军海军继承这个类 class Soldier(): def attack(self): pass back(self): pass 陆军 Army(Soldier): print("[陆军]搏击,ufc,无限制格斗,太极,八卦,占星,制作八卦符") [陆军]白天晨跑10公里,也行800百公里) 海军 Navy(Soldier): [海军]潜泳水下30个小时,手捧鱼雷,亲自送到敌人的老挝,炸掉敌人的碉堡) [海军]每小时在海底夜行800公里,游的比鲨鱼还快 空军 AirForce(Soldier): [空军]空中夺导弹,手撕飞机,在空中打飞机,精准弹幕[空军]高中跳伞,落地成盒 实例化陆军对象 army_obj = Army() 实例化海军对象 navy_obj = Navy() 实例化空军对象 af_obj = AirForce() lst = [army_obj,navy_obj,af_obj] 对象列表 strvar = """ 1.所有兵种开始攻击训练 2.所有兵种开始撤退训练 3.空军练习攻击,其他兵种练习撤退 """ print(strvar) num = input(将军请下令,选择训练的种类) for i in lst: if num == 1: i.attack() elif num == 2: i.back() 3: if isinstance(i,AirForce): i.attack() else: i.back() 将军~ 风太大 我听不见~) break __new__魔术方法关于魔术方法__new__1.触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 2.功能:控制对象的创建过程 3.参数:至少一个cls接受当前的类,其他根据情况决定 4.返回值:通常返回对象或None 基本语法(1)基本语法 MyClass2(): pty = 100 obj2= MyClass2() MyClass(): def __new__(cls): (cls) 类.方法(自定义类) => 借助父类object创建MyClass这个类的对象 obj = object. (1) 借助父类object创建自己类的一个对象 return obj (2) 返回其他类的对象 obj2 (3) 不返回任何对象 None obj = MyClass() print(obj) __new__ 触发时机快于构造方法__new__ 用来创建对象 __init__ 用来初始化对象 先创建对象,才能在初始化对象,所以__new__快于__init__ Boat(): print(2return object.(cls) __init__(self): print(1) obj = Boat() 因为__new__比__init__先执行,所以会先打印2后打印1. __new__ 和 __init__ 参数一一对应单个参数的情况 (cls,name): (self,name): self.name = name obj = Boat(友谊的小船说裂开就裂开print(obj.name) 多个参数的情况 当__init__参数很多的时候,在__new__方法使用*args和**kwargs收集所有的参数!! __new__(cls,*args,**kwargs): (cls) name self.color = color self.shangpai = shangpai obj = Boat(泰坦尼克号",屎绿色京A66688(obj.name) (obj.color) print(obj.shangpai) 关于__new__的注意点如果返回的对象不是自己本类中的对象,不会触发本类的构造方法 如果返回的对象不是自己本类中的对象,不会触发本类的构造方法 MyClass(): pty = 200 obj = MyClass() __new__(cls) 返回的是自己类的对象,会触发__init__方法 return obj # 返回的不是自己的对象,所以不会触发下面的__init__方法 return None # 没有返回对象,不可能触发__init__方法 构造方法被触发) obj = Boat() print(obj) 单态模式什么是单态模式?一个类,无论实例化多少个对象,都有且只有一个对象 单态模式的应用场景优点:节省内存空间,提升执行效率 针对于不要额外对该对象添加成员的场景(比如:mysql增删改查) 基本语法SingleTon(): __obj = None if cls.__obj is None: 把创建出来的对象赋值给私有成员__obj cls.__obj = object.return cls.__obj obj1 = SingleTon() obj2 = SingleTon() obj3 = SingleTon() (obj1,obj2,obj3) 第一次实例化对象时候,创建一个对象赋值给cls.__obj,返回 cls.__obj 第二次实例化对象时候,判定cls.__obj is None: 不成立,直接返回上一次创建好的那一个对象 第三次实例化对象时候,直接返回上一次创建好的那一个对象 """ 单态模式+构造方法kwargs): None: cls.__obj name obj1 = SingleTon(A) obj2 = SingleTon(B(obj1.name) (obj2.name) 打印出来的是两个B,原因如下 ''' obj1 = SingleTon(宋云杰) self.name = "A" obj2 = SingleTon(戈隆) self.name = "B" self 代表的是本对象 第一次实例化对象时候,创建一个对象,赋值name为A 第二次实例化对象时候,因为 cls.__obj is None不满足,返回上一个创建好的对象 为上一个对象的name这个属性赋值 为B obj1 和 obj2 所指代的对象是同一个对象 obj1.name => B obj2.name => B 其实有些相当于是B把A覆盖了,因为B和A指向同一个对象 ''' 连贯操作连贯操作,通过在类中的__init__方法中传入obj对象,进而实现对象.对象.对象.属性的这种连贯操作 通过.不停的调用下一个对象的操作就是连贯操作 1.小试牛刀MyClass1(): pth1 = 10 MyClass2(): obj obj = MyClass1() obj2 = MyClass2(obj) 对象.对象.属性 # obj2.obj = obj obj.pth1 = 10 print(obj2.obj.pth1) 10 2.升级版MyClass1(): pty1 = 101 func1(self): 我是func1函数) obj func2(self): 我是func2函数 MyClass3(): pty3 = 103 我是func3函数) obj1 = MyClass2(obj1) obj3 = MyClass3(obj2) 使用obj3调用func1方法? 对象.pty3 => obj2 | obj2.pty2 => obj1 | obj1.func1() obj3.pty3.pty2.func1() (obj3.pty3.pty2.pty1) obj3.pty3.func2() 连贯操作小项目->小人射击小人射击的项目需求小人射击项目的文件结构文件夹下: package包中: 小人射击项目的代码实现main.py(主函数) ### 小人射击 面向对象的核心思想: 把对象当做程序中的一个最小单元,让对象操作一切""" 弹夹: 属性: 子弹数量 bulletcount 方法: 无 枪 : 属性: 弹夹 方法: 射击 shoot 人 : 属性: 枪 方法: (1) 射击 (2) 换子弹 from package.bulletbox import BulletBox from package.gun Gun from package.person Person 先创建弹夹 danjia = BulletBox(20 在创建一杆枪 ak47 = Gun(danjia) 在创造一个人 songyunjie = Person(ak47,1)">宋云杰) 小人射击 if __name__ == __main__: 射击 songyunjie.fire(15) 填充 songyunjie.fillcount(10 在射击 songyunjie.fire(150) bulletbox.py(弹夹) ### 弹夹类 BulletBox():### 枪类 Gun(): 存放的是弹夹对象 self.bulletbox = bulletbox shoot(self,shootcount): if self.bulletbox.bulletcount < shootcount: 对不起,请先填充子弹~: 剩余的子弹 = 总的子弹数量 - 射击的数量 self.bulletbox.bulletcount -= shootcount 突" * shootcount,1)">你射出了{}发,还剩下{}发".format(shootcount,self.bulletbox.bulletcount)) person.py(人) ### 人类 Person(): gun self.name = " 填充子弹 fillcount(self,fillnum): 往弹夹里面赛子弹 self.枪对象 -> 弹夹对象 -> 弹夹数量属性 self.gun.bulletbox.bulletcount += fillnum 射击 fire(self,num): {}此刻正在野外射击~.format(self.name)) 枪对象.shoot self.gun.shoot(num) 关于小人射击项目的总结在小人项目中,.要时刻遵循面向对象的思想 1.在主函数main.py中,不要写任何逻辑,只写对象,让对象来操作一切 2.采用连贯操作,虽然实例化了三个对象,但是在调用方法的时候,只需要用一个对象去调用所有类中的方法 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |