python基础 03

面向对象

一般步骤

Step 1. 定义类
类是对象的蓝图和模板 有了类就可以创建对象
定义类需要做两件事:数据抽象和行为抽象
数据抽象 - 抽取对象共同的静态特征(找名词)- 属性
行为抽象 - 抽取对象共同的动态特征(找动词)- 方法
定义类的关键字 - class - 类名(每个单词首字母大写)
Step 2. 调用构造方法创建学生对象
实际上调用的是Student类中_init_方法
Step 3. 给对象发出消息
通过给对象发消息让对象完成某些工作
解决任何问题都是通过让对象去做事情

实例

步骤

# Step 1. 定义类
# 类是对象的蓝图和模板 有了类就可以创建对象
# 定义类需要做两件事:数据抽象和行为抽象
# 数据抽象 - 抽取对象共同的静态特征(找名词)- 属性
# 行为抽象 - 抽取对象共同的动态特征(找动词)- 方法
# 定义类的关键字 - class - 类名(每个单词首字母大写)

class Student:

    # 构造方法(构造器/构造子 -  construct)
    # 调用该方法时,不是直接使用方法的名字,而是使用类的名字
    def __init__(self, name, age):
        # 给对象绑定属性
        self.__name = name
        self.__age = age

    # 我们定义一个方法就代表对象可以接收这个消息
    # 对象的方法的第一个参数都是统一写成self
    # 它代表了接收消息的对象 - 对象.消息(参数)
    def study(self, course):
        print('%s正在学习%s, 年龄%d' % (self.__name, course, self.__age))

    def watch_av(self):
        if self.__age >= 18:
            print('%s正在看片, 年龄%d' % (self.__name, self.__age))
        else:
            print('%s我们推荐你看《熊出没》' % self.__name)


def main():
    # Step 2. 调用构造方法创建学生对象
    # 实际上调用的是Student类中__init__方法
    stu1 = Student('cfx', 24)
    # Step 3. 给对象发出消息
    # 通过给对象发消息让对象完成某些工作
    # 解决任何问题都是通过让对象去做事情
    stu1.study('python程序设计')
    stu2 = Student('王大锤', 5)
    stu2.__name = '刘备'
    stu2.__age = 20
    stu2.study('HTML')
    stu2.watch_av()


if __name__ == '__main__':
    main()

计算矩形的周长和面积

class Rectangle(object):

    def __init__(self, width, hight):
        self._width = int(width)
        self._hight = int(hight)

    def peri(self):
        return self._width * 2 + self._hight * 2

    def arer(self):
        return self._hight * self._width


def main1():
    rect1 = Rectangle('10', '5')
    print(rect1.peri())
    print(rect1.arer())

游泳池圆形过道及围栏花费

from math import pi

# 我们定义一个类实际上是把数据和操作数据的函数绑定到一起
# 形成了一个逻辑上的整体 这个整体就叫对象
# 而且将来任何时候想使用这种对象时直接复用这个类就可以了
class Circle(object):

    def __init__(self,radius = 0):
        self._radius = radius

    def area(self):
        return pi * self._radius ** 2

    def perimeter(self):
        return pi * self._radius * 2


def main():
    r = eval(input('请输入游泳池半径:'))
    big = Circle(r + 3)
    small = Circle(r)
    print('围墙的造价为%.2f' % (big.perimeter() * 35.5))
    print('过道的造价为%.2f' % ((big.area()-small.area()) * 25))


if __name__ == '__main__':
    main()

移动点和计算两点间距离

# 定义一个类 提供下面方法
# 移动点的方法(移动到 and 移动了)
# 计算一个点到另一个点距离的方法
class Dot(object):

    def __init__(self, x, y):
        self._x = x
        self._y = y

    def move(self, x, y):
        self._x += x
        self._y += y

    def goto(self, dx, dy):
        self._x = dx          
        self._y = dy

    def __str__(self):
        return '%s, %s' % (str(self._x), str(self._y))

    def distance(self, other):
        dx = self._x - other._x               # 此处other_x 可以优化
        dy = self._y - other._y
        return (dx ** 2 + dy ** 2) ** 0.5


class Calc(object):                           # 和 distance 作用一样

    def __init__(self, dot1,dot2):
        self._x1 = dot1._x
        self._y1 = dot1._y
        self._x2 = dot2._x
        self._y2 = dot2._y

    def __str__(self):
        return '%f' % (((self._x2 - self._x1) ** 2 + (self._y2 - self._y1) ** 2) ** 0.5)

def main():
    x1 = eval(input('请输入第一个点的x坐标:'))
    y1 = eval(input('请输入第一个点的y坐标:'))
    x2 = eval(input('请输入第二个点的x坐标:'))
    y2 = eval(input('请输入第二个点的y坐标:'))
    dot1 = Dot(x1, y1)
    dot2 = Dot(x2, y2)
    dot1.goto(5, 5)
    dot2.move(-1, -1)
    print(dot1)
    print(dot2)
    print(dot1.distance(dot2))
    calc1 = Calc(dot1, dot2)
    print(calc1)


if __name__ == '__main__':
    main()

实时数字时钟

学习time模块

_str变量 --- 在调用print函数时自动执行str里面的语句

import time


class Clock(object):
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    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

    # 下面的方法可以获得对象的字符串表示形式
    # 当我们用print打印对象时会自动调用该方法

    def __str__(self):
        """显示时间"""
        return '%02d : %02d : %02d' % \
               (self._hour, self._minute, self._second)


def main(h, m, s):
    clock = Clock(h, m, s)
    while True:
        # os.system('cls')
        print(clock)
        time.sleep(1)
        clock.run()


if __name__ == '__main__':
        # 开始时自动提取系统时间
    for _ in range(1):
        times = time.asctime()  # time 模块中的asctime不提供参数返回当前时间的字符串
        print(times)
    h = int(times[11:13])
    m = int(times[14:16])
    s = int(times[17:19])
    main(h, m, s)

判断两条线是否相交

分别判断一条线段的两个点是不是在另一条线段所在直线的两边

class Line(object):

    def __init__(self, x1, y1, x2, y2):
        self._x1 = x1
        self._y1 = y1
        self._x2 = x2
        self._y2 = y2

    def cross(self, other):
        a = (self._y2 * 10**3 - self._y1 * 10**3) / (self._x2 * 10**3 - self._x1 * 10**3)
        b = (self._y1 *10**9 - int(a *10**6) * self._x1 * 10**3)/10**9
        c = (other._y1 * 10 ** 9 - ((a * 10 ** 3) * (other._x1 * 10 ** 3)) * 10 ** 3 - b * 10 ** 9)/10 ** 9
        d = (other._y2 * 10 ** 9 - ((a * 10 ** 3) * (other._x2 * 10 ** 3)) * 10 ** 3 - b * 10 ** 9)/10 ** 9
        if c <= 0 and d >= 0 or c >= 0 and d <= 0:
            return True
        else:return False

    def __str__(self):
        return '点1(%.3f, %.3f);点2(%.3f, %.3f)' % (self._x1, self._y1, self._x2, self._y2)

def main():
    x11 = eval(input('请输入第一点x(最大精确到小数点后3位):'))
    y11 = eval(input('请输入第一点y(最大精确到小数点后3位):'))
    x12 = eval(input('请输入第二点x(最大精确到小数点后3位):'))
    y12 = eval(input('请输入第二点y(最大精确到小数点后3位):'))
    line1 = Line(x11, y11, x12, y12)
    print(line1)
    x21 = eval(input('请输入第一点x(最大精确到小数点后3位):'))
    y21 = eval(input('请输入第一点y(最大精确到小数点后3位):'))
    x22 = eval(input('请输入第二点x(最大精确到小数点后3位):'))
    y22 = eval(input('请输入第二点y(最大精确到小数点后3位):'))
    line2 = Line(x21, y21, x22, y22)
    print(line2)
    if line1.cross(line2) and line2.cross(line1):
        print('相交')
    else:
        print('不相交')

        
if __name__ == '__main__':
    main()

奥特曼打怪兽

奥特曼打怪兽原创版

import random, os


class Ultraman(object):
    def __init__(self, name, my_bool, strike_one, strike_two, attack_rate):
        self.name = name
        self.energy = 100
        self.my_bool = my_bool
        self.strike_one = strike_one
        self.strike_two = strike_two
        self.attack_rate = attack_rate

    def attack(self, other, m_one, two):

        if m_one:
            if random.randint(1, 100) <= self.attack_rate:
                other.m_bool -= self.strike_one
                return '奥特曼打中%s' % other.name
            else:
                return '奥特曼没打中%s' % other.name
        elif two and self.energy >= 30:
            if random.randint(1, 100) <= self.attack_rate:
                other.m_bool -= self.strike_two
                self.energy -= 30
                return '奥特曼打中%s' % other.name
            else:
                self.energy -= 30
                return '奥特曼没打中%s' % other.name
        else:
            return '能量不足'

    def hava_bool(self):
        return self.my_bool > 0

    def my_energy(self):
        if self.energy < 100:
            self.energy += 5

    def attacked(self):
        return '奥特曼的剩余血量:%d\t奥特曼的剩余能量:%d' % (self.my_bool, self.energy)

    def __str__(self):
        return '奥特曼的属性:%s\t血量:%d\t普通攻击力:%d\t强攻攻击力:%d\t攻击率:%d\t能量:%d' % \
          (self.name, self.my_bool, self.strike_one, self.strike_two, self.attack_rate, self.energy)


class Monster(object):
    def __init__(self,name):
        self.name = name
        self.m_bool = 100
        self.strike = random.randint(10,20)
        self.attack_rate = random.randint(50,85)

    def attack(self, other):
        if random.randint(1, 100) <= self.attack_rate:
            other.my_bool -= self.strike
            return '%s打中奥特曼' % self.name
        else:
            return '%s没打中奥特曼' % self.name

    def hava_bool(self):
        if self.m_bool > 0:
            return True
        else:
            return False

    def attacked(self):
        return '%s剩余血量%d' % (self.name, self.m_bool)

    def __str__(self):
        return '小怪兽的属性:%s\t血量:%d\t攻击力:%d\t攻击率:%d' % \
               (self.name, self.m_bool, self.strike, self.attack_rate)


def main():
    a = ['总血量','普通攻击力','强攻攻击力','攻击率(1,100)']
    for i in range(4):
        a.append(eval(input('请设置奥特曼%s' % a[i])))
    automan = Ultraman('automan', a[4], a[5], a[6], a[7])
    n = eval(input('你需要设置几个小怪兽:'))
    b1 = ['monster' + '%s' % (v + 1) for v in range(n)]
    for k in range(n):
        b1[k] = Monster(b1[k])
    os.system('cls')
    print(automan)
    for v in range(n):
        print(b1[v])
    method = input('''
    单挑 <--- 1
    群挑 <--- 2
    请输入进攻方式:''')
    if method == '1':
        for f in range(n):
            kk = 1
            os.system('cls')
            while automan.hava_bool() and b1[f].hava_bool():
                g = input('''第%d回合
                请选择进攻方式:
                普攻 <--- 1
                强攻 <--- 2''' % kk)
                one = True
                two = True
                if g == '1':
                    two = False
                elif g == '2':
                    one = False
                print(automan.attack(b1[f], one, two))
                print(b1[f].attack(automan))
                if b1[f].hava_bool():
                    print(b1[f].attacked())
                else:
                    print('%s剩余血量0' % b1[f].name)
                if automan.hava_bool():
                    print(automan.attacked())
                else:
                    print('奥特曼剩余血量0,奥特曼输了')
                    break
                automan.my_energy()
                go = input('''是否进入下一回合:
                          是<---1
                          否<---2''')
                if go == '2':
                    break
                else:
                    os.system('cls')
                kk += 1
            if f < n-1 and automan.hava_bool() and go != '2':
                print('奥特曼打死了%s,继续攻打下一只小怪兽' % b1[f].name)
            elif automan.hava_bool() and go != '2':
                print('奥特曼打死了%s,奥特曼赢了,游戏结束' % b1[f].name)

    elif method == '2':
        go_on = True
        kk = 1
        os.system('cls')
        s = n
        while go_on:
            g = input('''第%d回合
            请选择进攻方式:
            普攻 <--- 1
            强攻 <--- 2''' % kk)
            one = True
            two = True
            if g == '1':
                two = False
            elif g == '2':
                one = False
            for f in range(n):
                if automan.hava_bool() and b1[f].hava_bool():
                    print(automan.attack(b1[f], one, two))
                    automan.my_energy()
                    if b1[f].hava_bool():
                        print(b1[f].attacked())
                    else:
                        print('%s剩余血量0,被打死了' % b1[f].name)
                        s -= 1
            if s == 0:
                print('所有小怪兽都死了,奥特曼胜利')
                go_on = False
            for h in range(n):
                if b1[h].hava_bool() and automan.hava_bool():
                    print(b1[h].attack(automan))
                    if automan.hava_bool():
                        print(automan.attacked())
                    else:
                        print('奥特曼剩余血量0,奥特曼输了')
                        go_on =False
            go = input('''是否进入下一回合:
            是<---1
            否<---2''')
            if go =='2':
                break
            else:
                os.system('cls')
            kk += 1


if __name__ == '__main__':
    main()

奥特曼打怪兽修改版

通过_slots_魔法限定对象可以绑定的成员变量
_slots_不能继承,如果想子类有此特性,需要在子类重新写

from abc import ABCMeta, abstractmethod
from random import randint, randrange


class Fighter(object, metaclass=ABCMeta):
    """战斗者"""

    # 通过__slots__魔法限定对象可以绑定的成员变量  
    # __slots__不能继承,如果想子类有此特性,需要在子类重新写
    __slots__ = ('_name', '_hp')

    def __init__(self, name, hp):
        """
        初始化方法

        :param name: 名字
        :param 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 Ultraman(Fighter):
    """奥特曼"""

    __slots__ = ('_name', '_hp', '_mp')

    def __init__(self, name, hp, mp):
        """
        初始化方法

        :param name: 名字
        :param hp: 生命值
        :param mp: 魔法值
        """
        super().__init__(name, hp)
        self._mp = mp

    def attack(self, other):
        other.hp -= randint(15, 25)

    def huge_attack(self, other):
        """
        究极必杀技(打掉对方至少50点或四分之三的血)

        :param other: 被攻击的对象

        :return: 使用成功返回True否则返回False
        """
        if self._mp >= 50:
            self._mp -= 50
            injury = other.hp * 3 // 4
            injury = injury if injury >= 50 else 50
            other.hp -= injury
            return True
        else:
            self.attack(other)
            return False

    def magic_attack(self, others):
        """
        魔法攻击

        :param others: 被攻击的群体

        :return: 使用魔法成功返回True否则返回False
        """
        if self._mp >= 20:
            self._mp -= 20
            for temp in others:
                if temp.alive:
                    temp.hp -= randint(10, 15)
            return True
        else:
            return False

    def resume(self):
        """恢复魔法值"""
        incr_point = randint(1, 10)
        self._mp += incr_point
        return incr_point

    def __str__(self):
        return '~~~%s奥特曼~~~\n' % self._name + \
            '生命值: %d\n' % self._hp + \
            '魔法值: %d\n' % self._mp


class Monster(Fighter):
    """小怪兽"""

    __slots__ = ('_name', '_hp')

    def attack(self, other):
        other.hp -= randint(10, 20)

    def __str__(self):
        return '~~~%s小怪兽~~~\n' % self._name + \
            '生命值: %d\n' % self._hp


def is_any_alive(monsters):
    """判断有没有小怪兽是活着的"""
    for monster in monsters:
        if monster.alive:
            return True
    return False


def select_alive_one(monsters):
    """选中一只活着的小怪兽"""
    monsters_len = len(monsters)
    while True:
        index = randrange(monsters_len)
        monster = monsters[index]
        if monster.alive:
            return monster


def display_info(ultraman, monsters):
    """显示奥特曼和小怪兽的信息"""
    print(ultraman)
    for monster in monsters:
        print(monster, end='')


def main():
    u = Ultraman('骆', 1000, 120)
    m1 = Monster('舒', 250)
    m2 = Monster('白元芳', 500)
    m3 = Monster('王大锤', 750)
    ms = [m1, m2, m3]
    fight_round = 1
    while u.alive and is_any_alive(ms):
        print('========第%02d回合========' % fight_round)
        m = select_alive_one(ms)  # 选中一只小怪兽
        skill = randint(1, 10)   # 通过随机数选择使用哪种技能
        if skill <= 6:  # 60%的概率使用普通攻击
            print('%s使用普通攻击打了%s.' % (u.name, m.name))
            u.attack(m)
            print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        elif skill <= 9:  # 30%的概率使用魔法攻击(可能因魔法值不足而失败)
            if u.magic_attack(ms):
                print('%s使用了魔法攻击.' % u.name)
            else:
                print('%s使用魔法失败.' % u.name)
        else:  # 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)
            if u.huge_attack(m):
                print('%s使用究极必杀技虐了%s.' % (u.name, m.name))
            else:
                print('%s使用普通攻击打了%s.' % (u.name, m.name))
                print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
        if m.alive:  # 如果选中的小怪兽没有死就回击奥特曼
            print('%s回击了%s.' % (m.name, u.name))
            m.attack(u)
        display_info(u, ms)  # 每个回合结束后显示奥特曼和小怪兽的信息
        fight_round += 1
    print('\n========战斗结束!========\n')
    if u.alive > 0:
        print('%s奥特曼胜利!' % u.name)
    else:
        print('小怪兽胜利!')


if __name__ == '__main__':
    main()

可变参数、关键字参数、命名关键字参数

  • 可变参数 - 元组
    同样,如果想把一个元组当作可变参数传入,也需要在参数前加一个*
  • 关键字参数 - 字典 - 根据参数名来决定如何执行
    如果希望把一个字典当作关键词参数传入 需要在参数前放两个*
  • 命名关键字参数
    *号后面的参数必须要写成关键字参数形式,
    前面的可以给关键字参数形式也可以给可变参数形式,但关键字参数形式必须在可变参数后
# 关键字参数  -  字典  -  根据参数名来决定如何执行
# 可变参数  -  元组
def say_hello(*args,**kwargs):
    print(args)
    print(kwargs)
    if 'name' in kwargs:
        print('你好,%s' % kwargs['name'])
    elif 'age' in kwargs:
        age = kwargs['age']
        if age <= 16:
            print('你还是个小屁孩')
        else:
            print('你是一个成年人')
    else:
        print('请提供个人信息')


# 命名关键字参数
# *号后面的参数必须要写成关键字参数形式,
# 前面的可以给关键字参数形式也可以给可变参数形式,但关键字参数形式必须在可变参数后面
def foo(a, b, c, *, name, age):
    print(a + b + c)
    print(name, ':', age)

def main():
    say_hello(1,2,'hello',name='cfx',age=24, qq=12345689, gender=True)
    param = {'name': '王大锤', 'age': 330, 'qq': 12345689, 'gender': True}
    # say_hello(param)      #  会报错
    #  如果希望把一个字典当作关键词参数传入  需要在参数前放两个*
    say_hello(**param)
    #  同样,如果想把一个元组当作可变参数传入,也需要在参数前加一个*
    tuple1 = (5, 2, 'good')
    say_hello(*tuple1,**param)

    foo(a=1, b=2, c=3, name='cfx', age=24)
    foo(1, 2, 3, name='cfx', age=24)


if __name__ == '__main__':
    main()

装饰器

通过装饰器修饰f函数 让f函数在执行过程中可以做更多额外的操作

# 高内聚,低耦合


# 通过向函数中传入函数,可以写出更通用的代码
# calc函数中的第二个参数是另一个函数,它代表了一个二元运算
# 这样calc函数就不需要根某一特定的二元运算耦合在一起,
# 所以calc函数变得通用性更强,可以由传入的第二个参数来决定到底做什么
def calc(my_list, op):
    total = my_list[0]
    for index in range(1, len(my_list) - 1):
        total = op(my_list[index], total)
    return total


def add(x, y):
    return x + y


def mul(x, y):
    return x * y


def record(fn):
    def wrapper(*args, **kwargs):
        print('准备执行%s函数' % fn.__name__)
        print(args)
        print(kwargs)

        # 此行代码在执行被装饰的函数
        # 在这行代码的前后我们可以附加其他的代码
        # 这些代码可以让我们在执行函数时做一些额外的工作
        val = fn(*args, **kwargs)

        print('%s函数执行完成' % fn.__name__)
        print('返回了%d' % val)
        # 返回被装饰的函数的执行结果
        return val
    return wrapper


# 通过装饰器修饰f函数 让f函数在执行过程中可以做更多额外的操作
@record
def f(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * f(n-1)


if __name__ == '__main__':
    print(f(5))
    my_list = [1, 3, 5, 7, 8]
    print(calc(my_list, add))
    print(calc(my_list, mul))

继承、抽象类、抽象方法

# 线段上有两个点 - has-a - 关联
# 人使用了房子 - use-a - 依赖
# 学生是人 - is-a - 继承
# 继承 - 从已经有的类创建新类的过程
# 提供继承信息的称为父类(超类/基类)
# 得到继承信息的称为子类(派生类/衍生类)
# 通过继承我们可以将子类中的重复代码抽取到父类中
# 子类通过继承并复用这些代码来减少重复代码的编写
# 将来如果要维护子类的公共代码只需要在父类中操作就可以了
# 调用super().__init__(name,age,……)来绑定父类属性到子类

# 方法重写(override)- 覆盖 / 置换
# 子类在继承父类方法后对方法进行了重新实现
#  super().watch_av() # 传入父类方法的函数
# 当我们给子类对象发送watch_av消息时执行的是子类重写过的方法

# python没有从语言层面支持抽象的概念
# 我们可以通过abc模块来制造抽象类的效果
# 在定义类的时候通过制定metaclass=ABCMeta可以将类声明为抽象类
# 抽象类是不能创建对象的 抽象类存在的意义是专门拿给其他类继承
# abc模块中还有一个包装器abstractmethod
# 通过这个包装器可以将方法包装为抽象方法 必须要求子类进行重写
from abc import ABCMeta, abstractmethod


class Employee(object, metaclass=ABCMeta):
    """员工"""
    def __init__(self, name):
        """初始化方法"""
        self._name = name

    @property
    def name(self):
        return self._name

    @abstractmethod
    def get_salary(self):
        """获得月薪"""
        pass


class Manager(Employee,object):
    """部门经理"""
    def get_salary(self):
        return 15000


class Programmer(Employee):
    def __init__(self, name, working_hour = 0):
        # 子类重新定义了__init__后系统就会选用子类的__init__
        # 如果还需要父类的初始化属性需要添加super().__init__(……)
        super().__init__(name)
        self._working_hour = working_hour

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self, working_hour):
        self._working_hour = working_hour \
            if working_hour > 0 else 0

    def get_salary(self):
        return self.working_hour * 150


class Salesman(Employee):
    def __init__(self, name):
        super().__init__(name)
        self._sales = 0

    @property
    def sales(self):
        return self._sales

    @sales.setter
    def sales(self, sales):
        self._sales = sales if sales > 0 else 0

    def get_salary(self):
        return 1200 + self._sales * 0.05


def main():
    emps = [
        Manager('刘备'), Programmer('诸葛亮'),
        Manager('曹操'), Salesman('卢布'),
        Programmer('赵云'), Salesman('荀彧')
    ]
    for emp in emps:
        if isinstance(emp, Programmer):
            emp.working_hour = eval(input('请输入%s本月工作时间:' % emp.name))
        elif isinstance(emp, Salesman):
            emp.sales = float(input('请输入%s本月销售额:' % emp.name))
        # 同样是接收get_salary这个消息,但是不同的员工表现出了不同的行为
        # 因为三个子类都重写了get_salary方法,所以这个方法会表现出多态行为
        print('%s本月工资为:¥%.2f' % (emp.name, emp.get_salary()))


if __name__ == '__main__':
    main()

实例

计算矩形面积和周长

class Rectangle(object):

    __slots__ = ('_width', '_hight')
    def __init__(self, width, hight):
        self._width = eval(width)
        self._hight = eval(hight)

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, width):
        self._width = width if width > 0 else 0

    @property
    def hight(self):
        return self._hight

    @width.setter
    def width(self, hight):
        self._hight = hight if width > 0 else 0

    def peri(self):
        return self._width * 2 + self._hight * 2

    def arer(self):
        return self._hight * self._width


if __name__ == '__main__':
    rect1 = Rectangle('10', '5')
    print(rect1.peri())
    print(rect1.arer())
    width = 20
    hight = 30
    print(rect1.peri())
    print(rect1.arer())

模拟银行账户功能

class Account(object):
    def __init__(self, *, card_no, owner, banlance = 0):
        # *号后面的参数必须要写成关键字参数形式,
        self._card_no = card_no
        self._woner = owner
        self._banlance = banlance

    @property
    def banlance(self):
        return self._banlance

    def deposit(self, money):
        if money > 0:
            self._banlance += money
            return True
        return False

    def withdrow(self, money):
        if 0 < money <= self._banlance:
            self._banlance -= money
            return True
        return False

    def transfer(self, other, money):
        if self.withdrow(money):
            other.deposit(money)
            return True
        return False


def main():
    account = Account(card_no='12245', owner='王凯')
    account1 = Account(card_no='35222', owner='凯fjs')
    print(account.banlance)
    account.deposit(900)
    print(account1.banlance)
    print(account.banlance)
    if account.transfer(account1,1000):
        print(account1.banlance)
        print(account.banlance)
    else:
        print('余额不足')

    if account.transfer(account1,200):
        print(account1.banlance)
        print(account.banlance)
    else:
        print('余额不足')


if __name__ == '__main__':
    main()

定义一副扑克

from random import randrange


class Card(object):
    """一张牌"""
    def __init__(self, suite, face):
        self._suite = suite
        self._face = face

    @property
    def face(self):
        return self._face

    @property
    def suite(self):
        return self._suite

    def __str__(self):
        if self._face == 14:
            face_str = 'A'
        elif self._face == 11:
            face_str = 'J'
        elif self._face == 12:
            face_str = 'Q'
        elif self._face == 13:
            face_str = 'K'
        else:
            face_str = str(self._face)
        return '%s%s' % (self._suite, face_str)

class Poker(object):
    """一副牌"""
    def __init__(self):
        self._current = 0
        self._cards = []
        for suite in '♠♥♣♦':
            for face in range(2, 15):
                card = Card(suite, face)
                self._cards.append(card)

    @property
    def cards(self):
        return self._cards

    def shuffle(self):
        """洗牌"""
        cards_len = len(self._cards)
        for index in range(cards_len):
            pos = randrange(cards_len)
            self._cards[index], self._cards[pos] = \
                self._cards[pos], self._cards[index]

    @property
    def next(self):
        """发牌"""
        card = self._cards[self._current]
        self._current += 1
        return card

    @property
    def has_next(self):
        """还有没有牌"""
        return self._current < len(self.cards)



class Player(object):
    def __init__(self, name):
        self._name = name
        self._cards_on_hand = []

    @property
    def name(self):
        return self._name

    @property
    def hava(self):
        return self._cards_on_hand

    def get(self, card):
        self._cards_on_hand.append(card)

    def arrange(self):
        self._cards_on_hand.sort(key=get_key)


def get_key(card):
    return card.face



def main():
    p = Poker()
    p.shuffle()
    players = [
        Player('东邪'), Player('西毒'),
        Player('南帝'), Player('北丐')
    ]
    while p.has_next:
        for player in players:
            player.get(p.next)
    for player in players:
        player.arrange()
        print(player.name +':', end=' ')
        for cards in player.hava:
            print(cards, end='\t')
        print('')



if __name__ == '__main__':
    main()

21点扑克牌游戏(游戏)

需要用到上面定义的扑克牌

from poker import *


def cacl(list1):
    list2 = []
    for card in list1:
        if card.face == 11:
            list2.append(10)
        elif card.face == 12:
            list2.append(10)
        elif card.face == 13:
            list2.append(10)
        elif card.face == 14:
            list2.append(11)
            if sum(list2) > 21:
                list2.pop()
                list2.append(1)
        else:
            list2.append(int(card.face))
    if sum(list2) > 21 :
        for key in list2:
            if key == 11:
                list2.append(-10)
    return sum(list2)


def display(player):
    print('%s: ' % player.name, end='')
    for key in player.hava:
        print(key, end=' ')
    print('点数为:%d' % cacl(player.hava), end=' ')


def winer(player, m_player):
    if cacl(m_player.hava) <= 21:
        if cacl(m_player.hava) < cacl(player.hava) <=21:
            display(player)
            print('赢了')
        elif cacl(player.hava) > 21:
            display(player)
            print('爆了')
        elif cacl(player.hava) == cacl(m_player.hava):
            display(player)
            print('平局')
        else:
            display(player)
            print('输了')
    else:
        if cacl(player.hava) <= 21:
            display(player)
            print('赢了')
        elif cacl(player.hava) > 21:
            display(player)
            print('平局')


def main():
    p = Poker()
    p.shuffle()
    players = [
        Player('庄家'), Player('玩家1'),  Player('玩家2'),  Player('玩家3')
    ]
    while p.has_next:
        for i in range(2):
            players[0].get(p.next)
            p.cards.remove(players[0].hava[-1])
            if i == 0:
                print('%s:' % players[0].name, players[0].hava[i], end=' ')
            elif i == 1:
                print('*')
        for player in players[1:]:
            for i in range(2):
                player.get(p.next)
                p.cards.remove(player.hava[-1])
            display(player)
            print()
        for player in players[1:]:
            while cacl(player.hava) <= 21:
                go_on = input('%s是否继续拿牌?(y/n)' % player.name)
                if go_on == 'y':
                    player.get(p.next)
                    p.cards.remove(player.hava[-1])
                    display(player)
                    print()
                elif go_on == 'n':
                    break
        print('\n庄家继续拿牌')
        while cacl(players[0].hava) < 17:
            players[0].get(p.next)
            p.cards.remove(players[0].hava[-1])
        print('=================================')
        display(players[0])
        print()
        for player in players[1:]:
            winer(player, players[0])
        break


if __name__ == '__main__':
    main()

实现分数的加减乘除(运算符重载,集联编程)

# 运算符重载(重写)
# 集联编程
from math import gcd


class Fraction(object):

    def __init__(self, num, den):
        if den == 0:
            raise ValueError('分母不能为0')
        self._num = num
        self._den = den
        # self.normalize()
        # self.simplify()

    @property
    def num(self):
        return self._num

    @property
    def den(self):
        return self._den

    def normalize(self):
        """标准化"""
        if self._den < 0:
            self._den = -self._den
            self._num = -self._num
        return self                    # 返回self后才能集联编程

    def simplify(self):
        """化简"""
        if self._num != 0 and self._den != 1:
            factor = gcd(abs(self._den), abs(self._num))
            if factor > 1:
                self._num //= factor
                self._den //= factor
        return self                    # 返回self后才能集联编程

    def add(self, other):
        return Fraction(self._num * other.den + self._den * other.num, self._den * other.den).simplify().normalize()

    def sub(self, other):
        return Fraction(self._num * other.den - self._den * other.num, self._den * other.den).simplify().normalize()

    def mul(self, other):
        return Fraction(self._num * other.num, self._den * other.den).simplify().normalize()

    def div(self, other):
        return Fraction(self._num * other.den, self._den * other.num).simplify().normalize()

    def __add__(self, other):
        return self.add(other)

    def __sub__(self, other):
        return self.sub(other)

    def __mul__(self, other):
        return self.mul(other)

    def __truediv__(self, other):
        return self.div(other)

    def __str__(self):
        if self._num == 0:
            return '0'
        elif self._den == 1:
            return str(self._num)
        else:
            return '%d/%d' % (self._num, self._den)


def main():
   f1 = Fraction(-7, 25)
   f2 = Fraction(-7, 35)
   print(f1 + f2)
   print(f1 - f2)
   print(f1 * f2)
   print(f1 / f2)


if __name__ == '__main__':
    main()

五子棋(游戏)

import pygame

EMPTY = 0
BLACK = 1
WHITE = 2

black_color = [0, 0, 0]
white_color = [255, 255, 255]


class RenjuBoard(object):

    def __init__(self):
        self._board = [[0 for _ in range(15)] for __ in range(15)]   # 创建15个空列表的列表
        self.reset()

    def reset(self):
        for row in range(len(self._board)):
            self._board[row] = [EMPTY] * 15  # 清除棋盘所有棋子

    def check(self, row, col): # 判断输赢
        q = 1
        for i in range(1, 5):
            if row + i <= 14 and self._board[row][col] == self._board[row + i][col]:
                q += 1
            elif row - i >= 0 and self._board[row][col] == self._board[row - i][col]:
                q += 1
            else:
                q = 1
            if q >= 5:
                return True
        for i in range(1, 5):
            if col + i <= 14 and self._board[row][col] == self._board[row][col + i]:
                q += 1
            elif col - i >= 0 and self._board[row][col] == self._board[row][col - i]:
                q += 1
            else:
                q = 1
            if q >= 5:
                return True
        for i in range(1, 5):
            if row - i >= 0 and col - i >= 0 and self._board[row][col] == self._board[row - i][col - i]:
                q += 1
            elif row + i <= 14 and col + i <= 14 and self._board[row][col] == self._board[row + i][col + i]:
                q += 1
            else:
                q = 1
            if q >= 5:
                return True
        for i in range(1, 5):
            if row - i >= 0 and col + i <= 14 and self._board[row][col] == self._board[row - i][col + i]:
                q += 1
            elif row + i <= 14 and col - i >= 0 and self._board[row][col] == self._board[row + i][col - i]:
                q += 1
            else:
                q = 1
            if q >= 5:
                return True

    def move(self, row, col, is_black):
        if self._board[row][col] == EMPTY:
            self._board[row][col] = BLACK if is_black else WHITE
            return True
        return False

    def draw(self, screen):
        for i in range(40, 640, 40):
            pygame.draw.line(screen, black_color, [40, i], [600, i], 1)
            pygame.draw.line(screen, black_color, [i, 40], [i, 600], 1)  # 画线 做棋盘
        pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)  # 画矩形 36,36 表示起点 568 , 568 表示宽高 4 表示宽度
        pygame.draw.circle(screen, black_color, [320, 320], 5, 0)  # 绘制中心 5 为半径 0 为实心 1 为空心
        for i in range(160, 481, 320):
            for j in range(160, 481, 320):
                pygame.draw.circle(screen, black_color, [i, j], 5, 0)  # 绘制其他四个点
        for row in range(len(self._board)):
            for col in range(len(self._board[row])):
                if self._board[row][col] != EMPTY:
                    ccolor = black_color \
                        if self._board[row][col] == BLACK else white_color
                    pos = [40 * (col + 1), 40 * (row + 1)]
                    pygame.draw.circle(screen, ccolor, pos, 20, 0)


def main():
    black_win = pygame.image.load('win.jpg')  # 加载图片
    white_win = pygame.image.load('fall.jpg')
    board = RenjuBoard()
    is_black = True
    pygame.init() # 初始化
    pygame.display.set_caption('五子棋') # 设置标题
    screen = pygame.display.set_mode([640, 640]) # 设置屏幕大小
    screen.fill([255, 255, 0]) # 设置背景颜色
    board.draw(screen) # 绘制棋盘
    pygame.display.flip() # 刷新界面显示
    running = ok = True
    while running:
        for event in pygame.event.get(): #捕获所有事件,鼠标|键盘
            if event.type == pygame.QUIT: # 捕获点击退出事件
                running = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_q: # 捕获按下键盘q键
                board.reset() # 重置棋盘及棋子
                is_black = True # 重置棋色
                screen.fill([255, 255, 0]) # 重置背景颜色
                board.draw(screen) # 绘制棋盘及棋子(开始无棋子)
                pygame.display.flip() # 刷新出界面
            elif event.type == pygame.MOUSEBUTTONDOWN\
                    and event.button == 1: # 单机鼠标添加棋子
                x, y = event.pos  # 获取点击位置
                if 40 <= x <= 640 and 40 <= y <= 640: # 判断是点击位置是不是在棋盘上
                    row = round((y - 40) / 40)
                    col = round((x - 40) / 40)
                    if board.move(row, col, is_black):
                        is_black = not is_black
                        screen.fill([255, 255, 0])
                        board.draw(screen)
                        if board.check(row, col):
                            if not is_black: # 白棋赢显示的图片
                                screen.blit(black_win, (0, 20), (20, 0,800,800))
                            elif is_black: # 黑棋赢显示的图片
                                screen.blit(white_win, (90, 0), (40, 0,600,600))
                        if ok:
                            pygame.display.flip()

    pygame.quit()


if __name__ == '__main__':
    main()
·

大球吃小球(游戏)

from random import randint
import math
import pygame


class Ball(object):

    def __init__(self, center, color, radius, speed):
        self._center = center
        self._color = color
        self._radius = radius
        self._speed = speed

    @property
    def center(self):
        return self._center

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, new):
        self._radius = new

    def cross(self, other): # 判断一个球是否与另一个球重合,如果是,增加大球面积,让小球面积变为零
        x, y = self._center[0], self._center[1]
        x1, y1 = other.center[0], other.center[1]
        if math.sqrt((y1 - y) ** 2 + (x1 - x) ** 2) <= abs(self._radius - other.radius):
            if self._radius > other.radius:
                self.radius = int(math.sqrt(self._radius ** 2 + other.radius ** 2))
                other.radius = 0
            else:
                other.radius = int(math.sqrt(self._radius ** 2 + other.radius ** 2))
                self.radius = 0

    def move(self): # 更改每个球的坐标,实现移动,并在边界弹回来
        x, y = self._center[0], self._center[1]
        sx, sy = self._speed[0], self._speed[1]
        self._center = x, y = x + sx, y + sy
        if x + self._radius >= 800:
            self._speed = -abs(sx), sy
        elif x - self._radius <= 0:
            self._speed = abs(sx), sy
        if y + self._radius >= 600:
            self._speed = sx,-abs(sy)
        elif y - self._radius <= 0:
            self._speed = sx,abs(sy)

    def draw(self, screen): # 画出球
        pygame.draw.circle(screen, self._color, self._center,
                           self._radius, 0)


def main():
    balls = []
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('大球吃小球')
    clock = pygame.time.Clock() # 设置一个计时器
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN \
                    and event.button == 1:
                color = random_color()
                radius = randint(10, 100) # 球的半径
                speed = randint(-10, 10), randint(-10, 10) # 球x,y方向的移动速度及方向
                ball = Ball(event.pos, color, radius, speed)
                balls.append(ball)
        refresh(screen, balls)
        clock.tick(24) # 一秒刷新24次
        for ball in balls:
            ball.move() # 每个球开始移动
        if len(balls) >= 2:
            for num in range(len(balls)):
                for num1 in range(num + 1, len(balls)):
                    balls[num].cross(balls[num1]) #判断两个球是否重合,重合就吃掉小球,打球面积增加
    pygame.quit()


def refresh(screen, balls): # 刷新窗口界面
    bg_color = (240, 255, 240)
    screen.fill(bg_color)
    for ball in balls:
        ball.draw(screen)
    pygame.display.flip()


def random_color(): # 随机产生颜色
    red = randint(0, 255)
    green = randint(0, 255)
    blue = randint(0, 255)
    return red, green, blue


if __name__ == '__main__':
    main()

贪吃蛇(游戏)

from abc import ABCMeta, abstractmethod
from random import randint
import pygame

FOOD_COLOR = (51, 221, 43)
WALL_COLOR = (255, 0, 0)
GREEN_COLOR = (0, 255, 0)
UP = 0
RIGHT = 1
DOWN = 2
LEFE = 3


class GameObject(object, metaclass=ABCMeta):
    # 抽象类
    def __init__(self, x, y, color):
        self._color = color
        self._x = x
        self._y = y

    @abstractmethod # 抽象方法,子类必须拥有此方法
    def draw(self, screen):
        pass

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._y


class Wall(GameObject):
    def __init__(self, x, y, width, height, color=WALL_COLOR):
        super().__init__(x, y, color)
        self._width = width
        self._height = height

    @property
    def width(self):
        return self._width

    @property
    def height(self):
        return self._height

    def draw(self, screen): # 画出边框 也就是墙
        pygame.draw.rect(screen, self._color, (self._x, self._y, self._width, self._height), 5)
        # (屏幕,颜色,(起点x坐标,起点y坐标,宽度,高度),线宽)
        

class Food(GameObject):
    def __init__(self, x, y, size, color=FOOD_COLOR):
        super(Food, self).__init__(x, y, color)
        self._size = size
        self._show = True

    def new_dot(self):
        dot = [x for x in range(10, 610, 20)]
        self._x = dot[randint(0, len(dot) - 1)]
        self._y = dot[randint(0, len(dot) - 1)]

    def draw(self, screen): # 画食物,食物的坐标点是其左上角的点
        if self._show:
            pygame.draw.circle(screen, self._color,
                               (self._x + self._size // 2, self._y + self._size // 2), self._size // 2, 0)
            # (屏幕,颜色,(圆点x坐标,圆点y坐标),半径,实心0 or 空心1)
        self._show = not self._show


class SnakeNode(GameObject):
    # x, y 必须为基数(左上角坐标点),因为蛇移动的窗口的左上角坐标为(0,0)
    def __init__(self, x, y, size, color=GREEN_COLOR):
        super().__init__(x, y, color)
        self._size = size

    @property
    def size(self):
        return self._size

    def draw(self, screen): # 绘制蛇的节点和每个节点的边框
        pygame.draw.rect(screen, self._color, (self._x, self._y, self._size, self._size), 0)
        pygame.draw.rect(screen, (230, 255, 230), (self._x, self._y, self._size, self._size), 1)


class Snake(object): # 不能继承蛇的节点SnakeNode,蛇上有蛇的节点 是has a 关联关系 非继承关系
    def __init__(self):
        """
        定义蛇默认移动方向和长度
        """
        self._dir = LEFE
        self._nodes = []
        # 装蛇的每个节点,利用append向后依次装载
        for index in range(10):
            node = SnakeNode(290 + index * 20, 250, 20)
            self._nodes.append(node)

    @property
    def dir(self):
        return self._dir

    def change_dir(self, new_dir):
        """
        改变蛇的方向
        :param new_dir: 新的方向
        :return: 返回新的方向,如果新方向是原来方向或者原来方向的反方向则不返回
        """
        if (self._dir + new_dir) % 2 != 0:
            self._dir = new_dir

    def move(self):
        head = self._nodes[0]
        snake_dir = self._dir
        x, y, size = head.x, head.y, head.size
        if snake_dir == UP:
            y -= size
        elif snake_dir == RIGHT:
            x += size
        elif snake_dir == DOWN:
            y += size
        else:
            x -= size
        new_head = SnakeNode(x, y, size)
        self._nodes.insert(0, new_head)
        # 每次移动时在列表前面加一个节点,并删除最后一个节点
        self._nodes.pop()

    def collide(self, wall):
        """
        判断是否撞墙
        :param wall: 墙
        :return: 撞到返回True 否则返回False
        """
        head = self._nodes[0]
        x, y, size = head.x, head.y, head.size
        return x < wall.x or x > (wall.x + wall.width - size) or y < wall.y or y > (wall.y + wall.width - size)

    def eat_food(self, food):
        """
        判断是否吃到食物
        :param food: 食物对象
        :return: 吃到返回True,并记下最后一个节点属性,并加到最后。
        (由于蛇每次移动都会删掉最后一节尾巴并增加新的头,所以相当于此次没有删除蛇尾)
        """
        head = self._nodes[0]
        x, y, size = head.x, head.y, head.size
        if x == food.x and y == food.y:
            tail = self._nodes[-1]
            self._nodes.append(tail)
            return True

    def eat_me(self):
        """
        判断蛇是否吃到自己
        :return: 吃到返回True
        """
        head = self._nodes[0]
        x, y, size = head.x, head.y, head.size
        for a_node in self._nodes[4:]:
            ax, ay = a_node.x, a_node.y
            if abs(ax - x) < 20 and ay == y:
                return True
            if abs(ay - y) < 20 and ax == x:
                return True
            # 此处不能用elif,因为蛇在移动时不光检测两个方向,而是四个方向

    def draw(self, screen):
        """
        画出每个列表中每个节点
        :param screen: 画节点的屏幕
        :return: 可视化图形
        """
        for node in self._nodes:
            node.draw(screen)


def main():
    def handle_key_event(key_event):
        
        """
        处理按键事件
        :param key_event: 捕获的键盘事件
        :return: 新的方向
        """
        key = key_event.key
        if key == pygame.K_UP or key == pygame.K_w:
            new_dir = UP
        elif key == pygame.K_RIGHT or key == pygame.K_d:
            new_dir = RIGHT
        elif key == pygame.K_DOWN or key == pygame.K_s:
            new_dir = DOWN
        elif key == pygame.K_LEFT or key == pygame.K_a:
            new_dir = LEFE
        elif key == pygame.K_q:
            reset_game()
            return  # 加上return 让代码执行到此处后 后面的代码不在执行
        else:
            return
        if new_dir != snake.dir:
            snake.change_dir(new_dir)

    def reset_game():
        """
        重置游戏
        :return: 最初游戏状态
        (重新对蛇和食物赋值,并清空键盘事件(方向))
        """
        nonlocal snake, food
        snake = Snake()
        food = Food(190, 190, 20)
        pygame.event.clear()

    def refresh():
        """刷新游戏窗口"""
        food.draw(screen)
        wall.draw(screen)
        pygame.display.flip()

    def display_die():# 死亡后显示Game Over!
        font = pygame.font.SysFont('arial', 32)
        text = font.render('Game Over!', True, (255, 0, 0))
        screen.blit(text, (250, 260))

    def display_str(x):# 显示吃到食物数量
        font = pygame.font.SysFont('arial', 32)
        text = font.render('%s' % x, True, (255, 0, 0))
        screen.blit(text, (550, 20))

    snake = Snake()
    food = Food(190, 190, 20)
    wall = Wall(10, 10, 600, 600)
    pygame.init()
    screen = pygame.display.set_mode((620, 620))
    pygame.display.set_caption('贪吃蛇')
    screen.fill([244, 244, 244])
    pygame.display.flip()
    clock = pygame.time.Clock()
    running = True
    i = 0
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                handle_key_event(event)
        clock.tick(3)

        if not snake.collide(wall) and not snake.eat_me():
            snake.draw(screen)
            refresh()
            snake.move()
            #  move 和 refresh的位置不能改变,否则蛇死亡时会停在撞到的下一步
        else:
            display_die() # 此处没让蛇重新画,目的是当显示Game Over时蛇不会停在撞墙的下一步
            refresh()
        if snake.eat_food(food):
            i += 1
            food.new_dot()
        screen.fill([244, 244, 244])
        display_str(i)
    pygame.quit()


if __name__ == '__main__':
    main()

你可能感兴趣的:(python基础 03)