加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

day24:多态&魔术方法__new__&单态模式

发布时间:2020-12-20 09:56:30 所属栏目:Python 来源:网络整理
导读:目录 1.多态 2.__new__魔术方法 2.1?关于魔术方法__new__ 2.2?基本语法 2.3?__new__ 触发时机快于构造方法 2.4?__new__ 和 __init__ 参数一一对应 2.5?关于__new__的注意点 3.单态模式 4.连贯操作 5.小人射击项目 多态 什么是多态? 不同的子类对象 ,调用 相

目录

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.采用连贯操作,虽然实例化了三个对象,但是在调用方法的时候,只需要用一个对象去调用所有类中的方法

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读