day24:多态&魔术方法__new__&单态模式
目录
多态
什么是多态?
不同的子类对象,调用相同的父类方法,产生不同的执行结果
多态的关键字:继承和改写
下面的例子完美展示了python的多态:
# 定义Soldier类,让空军陆军海军继承这个类
class Soldier():
def attack(self):
pass def back(self):
pass # 陆军
class Army(Soldier):
def attack(self):
print("[陆军]搏击,ufc,无限制格斗,太极,八卦,占星,制作八卦符") def back(self):
print("[陆军]白天晨跑10公里,也行800百公里") # 海军
class Navy(Soldier):
def attack(self):
print("[海军]潜泳水下30个小时,手捧鱼雷,亲自送到敌人的老挝,炸掉敌人的碉堡") def back(self):
print("[海军]每小时在海底夜行800公里,游的比鲨鱼还快") # 空军
class AirForce(Soldier):
def attack(self):
print("[空军]空中夺导弹,手撕飞机,在空中打飞机,精准弹幕") def back(self):
print("[空军]高中跳伞,落地成盒") # 实例化陆军对象
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 == "":
i.attack()
elif num == "":
i.back()
elif num == "":
if isinstance(i,AirForce):
i.attack()
else:
i.back()
else:
print("将军~ 风太大 我听不见~")
break
__new__魔术方法
关于魔术方法__new__
1.触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
2.功能:控制对象的创建过程
3.参数:至少一个cls接受当前的类,其他根据情况决定
4.返回值:通常返回对象或None
基本语法
# (1)基本语法
class MyClass2():
pty = 100
obj2= MyClass2() class MyClass():
def __new__(cls):
print(cls)
# 类.方法(自定义类) => 借助父类object创建MyClass这个类的对象
obj = object.__new__(cls)
# (1) 借助父类object创建自己类的一个对象
return obj
# (2) 返回其他类的对象
return obj2
# (3) 不返回任何对象
return None obj = MyClass()
print(obj)
__new__ 触发时机快于构造方法
__new__ 用来创建对象
__init__ 用来初始化对象
先创建对象,才能在初始化对象,所以__new__快于__init__
class Boat():
def __new__(cls):
print(2)
return object.__new__(cls)
def __init__(self):
print(1) obj = Boat() # 因为__new__比__init__先执行,所以会先打印2后打印1.
__new__ 和 __init__ 参数一一对应
单个参数的情况
class Boat():
def __new__(cls,name):
return object.__new__(cls)
def __init__(self,name):
self.name = name obj = Boat("友谊的小船说裂开就裂开")
print(obj.name)
多个参数的情况
# 当__init__参数很多的时候,在__new__方法使用*args和**kwargs收集所有的参数!! class Boat():
def __new__(cls,*args,**kwargs):
return object.__new__(cls) def __init__(self,name,color,shangpai):
self.name = name
self.color = color
self.shangpai = shangpai obj = Boat("泰坦尼克号","屎绿色","京A66688")
print(obj.name)
print(obj.color)
print(obj.shangpai)
关于__new__的注意点
如果返回的对象不是自己本类中的对象,不会触发本类的构造方法
"""如果返回的对象不是自己本类中的对象,不会触发本类的构造方法"""
class MyClass():
pty = 200
obj = MyClass() class Boat():
def __new__(cls,*args,**kwargs):
return object.__new__(cls) # 返回的是自己类的对象,会触发__init__方法
# return obj # 返回的不是自己的对象,所以不会触发下面的__init__方法
# return None # 没有返回对象,不可能触发__init__方法
def __init__(self):
print("构造方法被触发")
obj = Boat()
print(obj)
单态模式
什么是单态模式?
一个类,无论实例化多少个对象,都有且只有一个对象
单态模式的应用场景
优点:节省内存空间,提升执行效率
针对于不要额外对该对象添加成员的场景(比如:mysql增删改查)
基本语法
class SingleTon():
__obj = None
def __new__(cls):
if cls.__obj is None:
# 把创建出来的对象赋值给私有成员__obj
cls.__obj = object.__new__(cls)
return cls.__obj obj1 = SingleTon()
obj2 = SingleTon()
obj3 = SingleTon()
print(obj1,obj2,obj3) """
第一次实例化对象时候, 创建一个对象赋值给cls.__obj,返回 cls.__obj
第二次实例化对象时候, 判定cls.__obj is None: 不成立, 直接返回上一次创建好的那一个对象
第三次实例化对象时候, 判定cls.__obj is None: 不成立, 直接返回上一次创建好的那一个对象
"""
单态模式+构造方法
class SingleTon():
__obj = None
def __new__(cls,*args,**kwargs): if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj def __init__(self,name):
self.name = name obj1 = SingleTon("A")
obj2 = SingleTon("B")
print(obj1.name)
print(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.小试牛刀
class MyClass1():
pth1 = 10 class MyClass2():
def __init__(self,obj):
self.obj = obj obj = MyClass1()
obj2 = MyClass2(obj)
# 对象.对象.属性
# obj2.obj = obj
# obj.pth1 = 10
print(obj2.obj.pth1) #
2.升级版
class MyClass1():
pty1 = 101
def func1(self):
print("我是func1函数") class MyClass2():
def __init__(self,obj):
self.pty2 = obj def func2(self):
print("我是func2函数") class MyClass3():
pty3 = 103
def __init__(self,obj):
self.pty3 = obj def func2(self):
print("我是func3函数") obj1 = MyClass1()
obj2 = MyClass2(obj1)
obj3 = MyClass3(obj2) # 使用obj3调用func1方法?
# 对象.pty3 => obj2 | obj2.pty2 => obj1 | obj1.func1()
obj3.pty3.pty2.func1()
print(obj3.pty3.pty2.pty1)
obj3.pty3.func2()
连贯操作小项目->小人射击
小人射击的项目需求
小人射击项目的文件结构
文件夹下:
package包中:
小人射击项目的代码实现
main.py(主函数)
# ### 小人射击
"""面向对象的核心思想: 把对象当做程序中的一个最小单元,让对象操作一切"""
"""
弹夹:
属性: 子弹数量 bulletcount
方法: 无
枪 :
属性: 弹夹
方法: 射击 shoot
人 :
属性: 枪
方法: (1) 射击 (2) 换子弹
"""
from package.bulletbox import BulletBox
from package.gun import Gun
from package.person import Person # 先创建弹夹
danjia = BulletBox(20)
# 在创建一杆枪
ak47 = Gun(danjia)
# 在创造一个人
songyunjie = Person(ak47,"宋云杰") # 小人射击
if __name__ == "__main__":
# 射击
songyunjie.fire(15)
# 填充
songyunjie.fillcount(10)
# 在射击
songyunjie.fire(150)
bulletbox.py(弹夹)
# ### 弹夹类 class BulletBox():
def __init__(self,bulletcount):
self.bulletcount = bulletcount
gun.py(枪)
# ### 枪类 class Gun():
def __init__(self,bulletbox):
# 存放的是弹夹对象
self.bulletbox = bulletbox def shoot(self,shootcount):
if self.bulletbox.bulletcount < shootcount:
print("对不起,请先填充子弹~")
else:
# 剩余的子弹 = 总的子弹数量 - 射击的数量
self.bulletbox.bulletcount -= shootcount
print("突" * shootcount , "你射出了{}发,还剩下{}发".format(shootcount,self.bulletbox.bulletcount))
person.py(人)
# ### 人类
class Person():
def __init__(self,gun,name):
self.gun = gun
self.name = "宋云杰" # 填充子弹
def fillcount(self,fillnum):
# 往弹夹里面赛子弹
# self.枪对象 -> 弹夹对象 -> 弹夹数量属性
self.gun.bulletbox.bulletcount += fillnum # 射击
def fire(self,num):
print("{}此刻正在野外射击~".format(self.name))
# 枪对象.shoot
self.gun.shoot(num)
关于小人射击项目的总结
day24:多态&魔术方法__new__&单态模式的更多相关文章
- 032.Python魔术方法__new__和单态模式
一 __new__ 魔术方法 1.1 介绍 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值 ...
- Learn day7 继承(单、多、菱形)\多态\魔术方法\装饰器\异常
1.继承 1.1 单继承# ### 继承 """ (1) 单继承 (2) 多继承 至少2个类,子类和父类 一个类继承另外一个类,当前类是子类 (衍生类) 被继承的这个类是 ...
- day19-Python运维开发基础(类的魔术方法)
1. __new__魔术方法 # ### __new__ 魔术方法 ''' 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当 ...
- PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结
前 言 OOP 学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1 PHP中的抽象 ...
- Python的程序结构[1] -> 方法/Method[2] -> 魔术方法 __init__ / __del__ / __new__
魔术方法 / Magic Method 魔法方法就是可以给你的类增加魔力的特殊方法(实质应称为特殊方法,魔术方法在JavaScript中有所体现,对象具有不透明特性,而且无法在自定义对象中模拟这些行为 ...
- Python的程序结构[1] -> 方法/Method[3] -> 魔术方法 __getattr__ 与代理模式
__getattr__ 方法 __getattr__ 方法当对象调用内部属性(包括方法等)且未找到对应属性的时候会调用的特殊方法.利用这一特性,可是对函数实现一个代理模式. __getattr__方法 ...
- PHP中设计模式以及魔术方法
1.设计模式 1.1单例模式 口诀:三私一公 1.私有的静态属性用来保存对象的单例 2.私有的构造方法用来阻止在类的外部实例化 3.私有的__clone阻止在类的外部clo ...
- Python 基础之面向对象之常用魔术方法
一.__init__魔术属性 触发时机:实例化对象,初始化的时候触发功能:为对象添加成员,用来做初始化的参数:参数不固定,至少一个self参数返回值:无 1.基本用法 #例:class MyClass ...
- Python魔术方法-Magic Method
介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...
随机推荐
- java 面向对象(二十三):关键字:abstract以及模板方法的设计模式
abstract abstract: 抽象的1.可以用来修饰:类.方法2.具体的:abstract修饰类:抽象类 * > 此类不能实例化 * > 抽象类中一定有构造器,便于子类实例化时调用 ...
- 老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化
引言 今天周末,我在家坐着掐指一算,马上又要到一年一度的金九银十招聘季了,国内今年上半年受到 YQ 冲击,金三银四泡汤了,这就直接导致很多今年毕业的同学会和明年毕业的同学一起参加今年下半年的秋招,这个 ...
- Dresdon简介
很久没有写文章了.这几年经历了很多事情:离开VMware的不舍,拿到融资的开心,重回VMware的亲切,以及不再争强好胜,只做自己喜欢事情的平和. 可以说,我是幸运的:我这一辈子都在选择,而不是被迫接 ...
- C# 泛型中的数据类型判定与转换
提到类型转换,首先要明确C#中的数据类型,主要分为值类型和引用类型: 1.常用的值类型有:(struct) 整型家族:int,byte,char,short,long等等一系列 浮点家族:float, ...
- echarts 实战 : 图表竖着或横着是怎样判定的?
这个问题比较简单. echarts 的图表默认是竖着的. 只要 xAxis 和 yAxis 互换,竖着的图就变成了横着的图了. 所以我们可以可以写一个xy轴互换的方法. reverseXYAxis = ...
- javascript : 对象取值练习
let obj = { "qqq":0, "www":0, "eee":0, "rrr":1, "ttt&qu ...
- vue项目打包踩坑记
基于webpack+vue-cli下的vue项目打包命令是 npm run build ,等待打包完成后在根目录生成dist文件夹,里面包含了所有项目相关的内容. 注意:需要完整版的vue-cli项目 ...
- LGV定理
LGV定理用于解决路径不相交问题. 定理 有 \(n\) 个起点 \(1, 2, 3, ..., n\),它们 分别对应 要到 \(n\) 个终点 \(A, B, C, ..., X\),并且要求路径 ...
- Pyramid attention networks for image restoration
paper:https://arxiv.org/abs/2004.13824 code: https://github.com/SHI-Labs/Pyramid-Attention-Networks ...
- git chechout
在克隆完一个的版本库时,git会在本地创建一个master分支用于跟踪远端的master分支 如git clone abc.git 默认情况下git会在本地创建一个master分支 但是,在本地mas ...