目录

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 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__&单态模式的更多相关文章

  1. 032.Python魔术方法__new__和单态模式

    一 __new__ 魔术方法 1.1 介绍 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值 ...

  2. Learn day7 继承(单、多、菱形)\多态\魔术方法\装饰器\异常

    1.继承 1.1 单继承# ### 继承 """ (1) 单继承 (2) 多继承 至少2个类,子类和父类 一个类继承另外一个类,当前类是子类 (衍生类) 被继承的这个类是 ...

  3. day19-Python运维开发基础(类的魔术方法)

    1. __new__魔术方法 # ### __new__ 魔术方法 ''' 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当 ...

  4. PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结

      前  言  OOP  学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1  PHP中的抽象 ...

  5. Python的程序结构[1] -> 方法/Method[2] -> 魔术方法 __init__ / __del__ / __new__

    魔术方法 / Magic Method 魔法方法就是可以给你的类增加魔力的特殊方法(实质应称为特殊方法,魔术方法在JavaScript中有所体现,对象具有不透明特性,而且无法在自定义对象中模拟这些行为 ...

  6. Python的程序结构[1] -> 方法/Method[3] -> 魔术方法 __getattr__ 与代理模式

    __getattr__ 方法 __getattr__ 方法当对象调用内部属性(包括方法等)且未找到对应属性的时候会调用的特殊方法.利用这一特性,可是对函数实现一个代理模式. __getattr__方法 ...

  7. PHP中设计模式以及魔术方法

    1.设计模式        1.1单例模式        口诀:三私一公 1.私有的静态属性用来保存对象的单例 2.私有的构造方法用来阻止在类的外部实例化 3.私有的__clone阻止在类的外部clo ...

  8. Python 基础之面向对象之常用魔术方法

    一.__init__魔术属性 触发时机:实例化对象,初始化的时候触发功能:为对象添加成员,用来做初始化的参数:参数不固定,至少一个self参数返回值:无 1.基本用法 #例:class MyClass ...

  9. Python魔术方法-Magic Method

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...

随机推荐

  1. python面试题七: mysql数据库

    ---------------------------------------------------------------------------------------------------- ...

  2. Python之 爬虫(十二)关于深度优先和广度优先

    网站的树结构 深度优先算法和实现 广度优先算法和实现 网站的树结构 通过伯乐在线网站为例子: 并且我们通过访问伯乐在线也是可以发现,我们从任何一个子页面其实都是可以返回到首页,所以当我们爬取页面的数据 ...

  3. bzoj3437小P的牧场

    bzoj3437小P的牧场 题意: n个牧场,在每个牧场见控制站的花费为ai,在该处建控制站能控制从此处到左边第一个控制站(或边界)之间的牧场.一个牧场被控制的花费等于它到控制它的控制站之间的牧场数目 ...

  4. python利用difflib判断两个字符串的相似度

    我们再工作中可能会遇到需要判断两个字符串有多少相似度的情况(比如抓取页面内容存入数据库,如果相似度大于70%则判定为同一片文章,则不录入数据库) 那这个时候,我们应该怎么判断呢? 不要着急,pytho ...

  5. 将python3打包成为exe可执行文件(pyinstaller)

    我们工作中可能会遇到,客户需要一个爬虫或者其他什么功能的python脚本. 这个时候,如果我们直接把我们的python脚本发给客户,会有两个问题: 1.客户的电脑或者服务器可能并没有安装python环 ...

  6. python也能玩视频剪辑!moviepy操作记录总结

    前几篇文章咱们介绍了一下图片的处理方式,今天咱们说说视频的处理.python能够支持视频的处理么?当然是肯定的,人生苦读,我用python.万物皆可python. moviepy库安装 今天咱们需要使 ...

  7. 上亿数据怎么玩深度分页?兼容MySQL + ES + MongoDB

    面试题 & 真实经历 面试题:在数据量很大的情况下,怎么实现深度分页? 大家在面试时,或者准备面试中可能会遇到上述的问题,大多的回答基本上是分库分表建索引,这是一种很标准的正确回答,但现实总是 ...

  8. RocketMQ在面试中那些常见问题及答案+汇总

    0.汇总 RocketMQ入门到入土(一)新手也能看懂的原理和实战! RocketMQ入门到入土(二)事务消息&顺序消息 从入门到入土(三)RocketMQ 怎么保证的消息不丢失? Rocke ...

  9. mybatis自动生成代码插件mybatis-generator使用流程(亲测可用)

    mybatis-generator是一款在使用mybatis框架时,自动生成model,dao和mapper的工具,很大程度上减少了业务开发人员的手动编码时间 坐着在idea上用maven构建spri ...

  10. Zabbix4.x如何安全传输数据

    由于设备都在混合云,所以不少数据传输是通过公网,这样极大的增加了危险性,所以在Zabbix数据传输这块则进行PSK安全认证,由proxy主动收集agent数据后统一发送给server,这样只需要对pr ...