文章目录
今日知识点
- 常用魔法方法
- 单例模式
1.魔法方法
1.魔法方法介绍
在Python中,有一些内置好的特定方法,这些方法在进行特定的操作时会自动被调用,称为魔法方法。
魔法方法的命名总是被双下划线包围,比如__名称__
2.常用魔法方法
1. doc
- 用来查看类的说明文档
练习:
- 查看列表类的说明文档
print(list.__doc__)
# list() -> new empty list
# list(iterable) -> new list initialized from iterable's items
可以去看一下说明文档,是一模一样的
2. dict
- 用于获取类或者实例的属性字典
class Student:
def __init__(self):
self.name = 'jeff'
self.age = 18
def text(self):
self.city = '长沙'
s = Student()
s.text()
print(s.__dict__)
# {'name': 'jeff', 'age': 18, 'city': '长沙'}
注意:
- 实例属性存储在对象中,所以通过 对象.__dict__ 获取的是实例属性
- 除实例属性以外的成员都存储在类中,所以通过 类.__dict__ 来获取
3. del ()
- 叫做析构方法。当由该类创建的实例对象,被删除或者说在内存中被释放,将会自动触发执行。
class Demo:
def __del__(self):
print('——1——')
s = Demo()
print('——2——')
print('——3——')
'''
输出结果为
——2——
——3——
——1——
全部执行完毕才会触发__del__
'''
总结:
- 当代码全部执行完毕才自动触发__del__()
- 如果需要提前触发,则需要通过del关键字,删除所有对象后触发__del__()
class Demo:
def __del__(self):
print('——1——')
s = Demo()
print('——2——')
del s # 通过关键字 del 将对象删除,则会主动调用__del__方法
print('——3——')
'''
——2——
——1——
——3——
'''
'''
注意:
- 此方法一般不需要定义,因为 Python 是一门高级语言,程序员在使用时无需关心内存的分配与释放,一般都是交给 Python 解释器来执行。所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行。
4. call ()
- 用于将对象变成一个可调用的对象。也就是说,当一个类中有__call__()方法时,其实例化得到的对象便是可调用的(callable)
class Demo:
def __init__(self):
print(123)
d = Demo()
d() # TypeError: 'Demo' object is not callable
# 相当于Demo()() 所以报错
但是使用了__call__方法,就变成可调用的了
class Demo:
def __init__(self):
print(123)
def __call__(self, *args, **kwargs):
print('可以调用了')
d = Demo()
d()
# 123
# 可以调用了
5. new ()
练习:代码打印输出的顺序是什么?
- A.__init__,__ new__
- B.__init__
- C.__ new__
- D.__ new__, __init__
class Demo(object):
def __init__(self):
print(123)
def __new__(cls, *args, **kwargs):
print(456)
# 由于在此处重写了父类的new方法,所以对象并未创建,不会触发__init__方法
s = Demo()
# 456:只调用到了__new__
# __new__:用来创建对象的
# __init__:创建对象之后自动调用
- 用于创建与返回一个对象。在类准备将自身实例化时调用。
注意: - __new__() 方法用于创建对象
- __init__() 方法在对象创建的时候,自动调用
- 但是此处重写了父类的 __new__() 方法,覆盖了父类__new__() 创建对象的功能,所以对象并没有创建成功。所以仅执行 __new__() 方法内部代码
对象创建执行顺序
- 1.通过\ _new_() 方法 创建对象
- 2.并将 对象返回,传给 __init__()
思路: - 重写父类 __new__() 方法
- 并且在该方法内部,调用父类的 __new__() 方法
注意
- 在创建对象时,一定要将对象返回,才会自动触发__init__()方法
- init()方法当中的self,实际上就是__new__返回的实例,也就是该对象__init__()与__new__()区别:
- __init__实例方法,__new__静态方法
- __init__在对象创建后自动调用,__new__创建对象的方法
2.单例模式
1.单例模式介绍
- 单例模式是一种常用的软件设计模式。也就是说该类只包含一个实例。
- 通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
- 通常应用在一些资源管理器中,比如日志记录等
2.单例模式实现
思路
- 当对象不存在时,创建对象
- 当对象存在时,永远返回当前已经创建对象
3.作业
1.作业
- 士兵老Amy有一把枪(AK47),
- 士兵可以开火
- 枪能够发射子弹
- 枪能够添加子弹
- 枪类:
- 属性:型号,子弹数量
- 行为:发射子弹,添加子弹
- 士兵类:
- 属性:士兵名称,枪支
- 行为:开火行为(需考虑到:是否有枪支?以及添加子弹,发射子弹
class ArmymanAmy(object):
def __init__(self, name, goods):
self.armyman = name
self.goods = goods
class Gun(ArmymanAmy):
def __init__(self, model, name, goods):
super().__init__(name, goods)
self.model = model
self.bullet = 0
def fire(self):
self.bullet += s
if self.goods == '有枪' and self.bullet > 0:
print(f'{self.armyman}端着那粉色的{self.model}, 用那{self.bullet}发子弹扫爆你脑袋')
self.bullet -= w
print(f'{self.armyman}开了{w}枪,还剩下{self.bullet}发子弹')
elif self.model == '没枪':
print('枪都没有你打什么')
elif self.bullet <= 0:
print('子弹都没有你打什么')
name = input('请输入士兵的名字:')
goods = input('请输入\'有枪\'或者\'没枪\':')
model = input('请输入什么枪:')
s = int(input('请输入子弹数量:'))
w = int(input('打多少发子弹'))
a = Gun(model, name, goods)
a.fire()
2.作业
- 车类1:
- 属性:颜色,轮子个数(默认4个),重量级,速度(默认为0)
- 行为:加速,减速,停车
- 车类2:
- 属性:在基于车类1的基础上,添加一些比如:牌子,型号,空调系统等
- 行为:覆盖车类1的加速与减速,打印输出车辆信息
import time
class Car:
def __init__(self, color, weight): # 属性
self.color = color # 颜色
self.wheel = 4 # 轮子
self.weight = weight # 重量
self.speed = 0 # 速度
self.accelerate = '加速'
self.slow_dowm = '减速'
self.stop = '停车'
def action(self): # 行为
self.speed = 2
print(f'现在{self.accelerate},当前速度为{self.speed}')
time.sleep(2)
self.speed = 1
print(f'现在{self.slow_dowm},当前速度为{self.speed}')
time.sleep(2)
self.speed = 0
print(f'现在{self.stop},当前速度为{self.speed}')
class Car_2(Car): # 继承父类
def __init__(self, air_conditioner, brand, model, color, weight):
super().__init__(color, weight) # 超类调用父类的属性
self.air_conditioner = air_conditioner # 空调
self.brand = brand # 牌子
self.model = model # 型号
def action(self): # 覆盖父类的方法
print(
f'这是一辆有{self.air_conditioner},轮子个数为{self.wheel}的,{self.color}{self.model}跑车,车牌为{self.brand},重量{self.weight}KG。')
c = Car_2('空调', '粤A 00000', 'Lamborghini 毒药', '黑色', '2000')
c.action()