Python-100天从新手到大师-学习笔记(三)

写在最前面

因为种种原因,喜提史上最长寒假。
在家闲来无事,同时因为项目需要用到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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值