写在最前面
因为种种原因,喜提史上最长寒假。
在家闲来无事,同时因为项目需要用到python相关内容(其实是keras,没现成的代码,自己改又不会改),所以打算开始学习python。
这个系列算是笔记,详细的学习内容请大家移步骆昊老师的GitHub。
Python - 100天从新手到大师
面向对象相关
这部分用一个奥特曼打小怪兽的例子来记忆或许更好。
奥特曼打小怪兽
有一个奥特曼和多只小怪兽,奥特曼可以使用普通攻击,或者消耗MP使用魔法攻击,也可以消耗大量MP使用大招。其中魔法攻击为AOE伤害,普通攻击和大招为单体伤害。受到单体伤害的小怪兽,会反击。
from abc import ABCMeta, abstractmethod
from random import randint, randrange
class Fighter(object, metaclass=ABCMeta):
'''战斗者'''
#限定只能添加_name, _hp两个属性,只对Fighter类有效
#对于建议私有(不可修改)的属性,一般以_开头
__slots__ = ('_name', '_hp')
def __init__(self, name, hp):
self._name = name
self._hp = hp
@property
def name(self):
return self._name
#访问器,只能访问,不可修改
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >= 0 else 0
#修改器,允许修改
@property
def alive(self):
return self._hp > 0
@abstractmethod
def attack(self, other):
''':param other: 被攻击者'''
pass
#静态方法,有形无实
class Ultrman(Fighter):
'''奥特曼'''
#Fighter类的子类,继承
__slots__ = ('_name', '_hp', '_mp')
def __init__(self, name, hp, mp):
super().__init__(name, hp)#初始化,父类中有的可用
self._mp = mp
def attack(self, other):
'''普通攻击'''
other.hp -= randint(10, 15)
def magic_attack(self, others):
'''
一次消耗20mp, AOE伤害
mp不足则攻击失败
'''
if self._mp >= 20:
self._mp -= 20
for temp in others:
if temp.alive:
temp.hp -= randint(10, 30)
return True
else:
print('------mp不足,变为普通攻击-------\n')
return False
def huge_attack(self, other):
'''
大招,3/4血量或至少50
蓝耗 50
'''
if self._mp >= 50:
injure = other.hp / 4 * 3
other.hp -= 50 if 50 > injure else injure
return True
else:
print('------mp不足,变为普通攻击-------\n')
return False
def resum(self):
'''
每次普攻随机恢复【1,10】点mp
'''
increase = randint(1, 10)
self._mp += increase
return increase
def __str__(self):#显示信息
return '\n%s:\n' % self.name + \
'生命值: %d ' % self.hp + \
'魔法值: %d' % self._mp
class Monster(Fighter):
__slots__ = ('_name', '_hp')
def attack(self, other):
other.hp -= randint(5, 30)
def __str__(self):
return '%s:\n' % self.name + \
'生命值: %d' % self.hp
def is_any_alive(monsters):
for monster in monsters:
if monster.alive:
return True
return False
def select_monster(monsters):
number_monster = len(monsters)
while True:
index = randint(0, number_monster - 1)
if monsters[index].alive:
return monsters[index]
def display_info(ultraman, monsters):#显示__str__方法下的信息
print(ultraman)
for monster in monsters:
print(monster, end='\n')
def main():
u = Ultrman('广大人民群众', 1000, 1000)
m1 = Monster('湖北红10', 10000)
m2 = Monster('湖北省长', 10000)
m3 = Monster('武汉市长', 10000)
ms = [m1, m2, m3]
fight_round = 0
while u.alive and is_any_alive(ms):
fight_round += 1
print('\n=======第%d回合========' % fight_round)
m = select_monster(ms)
i = randint(1, 10)
if i <= 6:
u.attack(m)
print('%s 使用普通攻击 攻击了 %s' % (u.name, m.name))
print('%s 恢复魔法: %d' % (u.name, u.resum()))
elif i <= 9:
if u.magic_attack(ms):
print('%s 使用魔法攻击' % u.name)
else:
u.attack(m)
print('%s 使用普通攻击 攻击了 %s' % (u.name, m.name))
print('%s 恢复魔法: %d' % (u.name, u.resum()))
else:
if u.huge_attack(m):
print('%s 使用了大招' % u.name)
else:
u.attack(m)
print('%s 使用普通攻击 攻击了 %s' % (u.name, m.name))
print('%s 恢复魔法: %d' % (u.name, u.resum()))
if m.alive:
m.attack(u)
print('%s 回击了 %s' % (m.name, u.name))
display_info(u, ms)
print('====战斗结束====')
if u.alive:
print('%s 获胜' % u.name)
else:
print('这届网友不行')
if __name__ == '__main__':
main()
关于静态方法
和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,代码如下所示。
from time import time, localtime, sleep
class Clock(object):
"""数字时钟"""
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
# 通过类方法创建对象并获取系统时间
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()