目录

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. 读《大话设计模式》——应用工厂模式的"商场收银系统"(WinForm)

    要做的是一个商场收银软件,营业员根据客户购买商品单价和数量,向客户收费.两个文本框,输入单价和数量,再用个列表框来记录商品的合计,最终用一个按钮来算出总额就可以了,还需要一个重置按钮来重新开始. 核心 ...

  2. Scala 基础(四):Scala变量 (一) 基础

    1.概念 变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门 牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值). 2 变量使用的基本步骤 1) 声明/定义变量 ( ...

  3. HotSpot VM运行时

    HotSpot VM运行时系统为HotSpot JIT编译器和垃圾收集器提供服务和通用API,同时还为VM提供启动.线程管理.JNI(Java本地接口)等基本功能.HotSpot VM运行时环境担当许 ...

  4. 太实用了!自己动手写软件——SSH、FTP和SQL server的密码破解

    我们的密码破解工具一共分为如下六个部分,前面四个部分我们都有在之前的文章中介绍过了 用户图形界面——GUI编程 密码字典获取——Excel文件读取 数据库类——MySQL.Oracle和SQL ser ...

  5. Mesos+Zookeeper+Marathon+Docker环境搭建

    相关理论请参考:https://www.cnblogs.com/Bourbon-tian/p/7155054.html,本文基于https://www.cnblogs.com/Bourbon-tian ...

  6. Python Ethical Hacking - KEYLOGGER(2)

    Report function: Run in the background. Don't interrupt program execution. Every X seconds, send the ...

  7. ES6标准中的import和export

    在ES6前, 前端使用RequireJS或者seaJS实现模块化, requireJS是基于AMD规范的模块化库,  而像seaJS是基于CMD规范的模块化库,  两者都是为了为了推广前端模块化的工具 ...

  8. 题解 洛谷 P3734 【[HAOI2017]方案数】

    可以先考虑没有障碍物的情况,设计状态\(f_{i,j,k}\),表示到达坐标 \((x,y,z)\)二进制下,\(x\)有\(i\)位,\(y\)有\(j\)位,\(z\)有\(k\)位的方案数. 得 ...

  9. python的__get__方法看这一篇就足够了

    get类型函数 直接上代码: class TestMain: def __init__(self): print('TestMain:__init__') self.a = 1 if __name__ ...

  10. 在 Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO

    我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动 ...