Python第三周习题集(一) (工资结算系统 抽象类 静态方法 贪吃蛇 分数的重写 五子棋 大球吃小球 )
# 工资结算系统 1. 部门经理 1.5万元/月 2. 程序员 工作时间 150元/小时 3.销售员 1200底薪,+ %5销售额的提成 # 给你员工,得出工资。 员工类,父类 下面3类子类。
#我写的
class Staff(object): def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age class Department_manager(Staff): def __init__(self, name, age, salary): super().__init__(name, age) self._salary = salary @property def salary(self): return self._salary def get_money(self): print('%s岁的%s工作了一个月挣了%s' % (self._age, self._name, self._salary)) class Programer(Staff): def __init__(self, name, age, salary): super().__init__(name, age) self._salary = salary @property def salary(self): return self._salary def get_money(self, time): print('%s岁的%s工作了一个月共%s小时挣了%s' % (self._age, self._name, time, self._salary * time)) class Salesman(Staff): def __init__(self, name, age, sale): super().__init__(name, age) self._sale = sale @property def salary(self): return self._sale def get_money(self): salary = self._sale * 5 / 100 + 1200 print('销售员%s一个月挣了%s' % (self._name, salary)) def main(): which = str(input('请输入员工类型:部门经理/程序员/销售员')) if which == '部门经理': name = input('请输入名字') age = input('请输入年龄') man1 = Department_manager(name, age, '1.5万元') print(man1.get_money()) elif which == '程序员': name = input('请输入名字') age = input('请输入年龄') man2 = Programer(name, age, 150) time = int(input('请输入工作了多少小时')) print(man2.get_money(time)) elif which == '销售员': name = input('请输入名字') age = input('请输入年龄') sale = int(input('请输入销售额')) man3 = Salesman(name, age, sale) print(man3.get_money()) if __name__ == '__main__': main()
抽象类
Python没有从语言层面支持抽象类的概念,我们可以从abc模块来制造抽象类的效果。
在定义类的时候,通过指定metaclass=ABCMeta可以将类声明为抽象类
抽象类是不能创建对象的,抽象类只是拿来被继承的,给其他类继承
abc模块中还有一个叫abstractmethon,通过这个包装器,可以将方法包装为抽象方法,必须要求子类重写。
rom abc import ABCMeta, abstractmethod class Employee(object, metaclass=ABCMeta): """员工""" def __init__(self, name, age): """初始化方法""" self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age @abstractmethod # 变型为抽象类,以下的子类继承这个的时候,必须重写这个方法。 def get_salary(self): """计算月薪""" pass class Manager(Employee): def __init__(self, name, age): super().__init__(name, age) def get_salary(self): return 15000 class Programer(Employee): def __init__(self, name, age): super().__init__(name, age) self._working_hour = 0 @property def working_hour(self): return self._working_hour # 非必要属性,通过setter方法给出,必要属性,通过属性给出,不轻易修改 @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, age): super().__init__(name, age) 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 * 5 / 100 def main(): emps = [ Manager('曹宇', 22), Programer('杨茜然', 22), Manager('张超', 22), Programer('李西北', 22), Salesman('刘家咯', 22) ] for emp in emps: # 识别类型,很重要******* if isinstance(emp, Programer): emp.working_hour = int(input('请输入%s本月工作时间:' % emp.name)) elif isinstance(emp, Salesman): emp.sales = int(input('请输入%s本月销售额:' % emp.name)) # 同样是接受get_salary这个消息,但是不用员工表现出了不同行为 # 因为三个子类都重写了这个方法,所以这个方法会表现出多态行为 print('%s本月工资为:¥%.2f元' % (emp.name, emp.get_salary())) if __name__ == '__main__': main()
静态方法
是用来发给这个类的爸爸的,不是发给这个类的。有两种方法。
1.@staticmethon
2.@classmethon 下面这个比上面这个多了一个参数,(cls)
from math import sqrt class Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c # 静态方法, 用以发给类,不是发给对象的。就是发给它爸爸的。 # @staticmethod # @classmethod 也是发给类的,区别, # def is_valid(a, b, c): # return a + b > c and a + c > b and b + c > a @classmethod # @classmethod 也是发给类的,区别, def is_valid(cls, a, b, c): return a + b > c and a + c > b and b + c > a @property def perimeter(self): return self._a + self._b + self._c @property def area(self): half = self.perimeter / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main(): a = b = c = 1 if Triangle.is_valid(a, b, c): # 静态方法。 t = Triangle(a, b, c) print(t.perimeter) # 对象来执行 # 或者用 (Triangle.perimeter(t)) 类来执行,传入参数。 print(t.area) else: print('无法构成三角形!') if __name__ == '__main__': main()
贪吃蛇
import pygame from random import randint from abc import ABCMeta, abstractmethod BLACK_COLOR = (0, 0, 0) FOOD_COLOR = (236, 111, 187) GREEN_COLOR = (0, 255, 0) UP = 0 RIGHT = 1 DOWN = 2 LEFT = 3 class GameObject(object, metaclass=ABCMeta): def __init__(self, x=0, y=0, color=BLACK_COLOR): self._x = x self._y = y self._color = color @property def x(self): return self._x @property def y(self): return self._y @property def color(self): return self._color @abstractmethod # 后面继承的子类都必须重写此方法,不然报错 def draw(self, screen): pass class SnakeNode(GameObject): # 蛇节 def __init__(self, x, y, size, color=GREEN_COLOR): """ x y 为坐标,size为宽高。 :param x: :param y: :param size: :param color: """ super(SnakeNode, self).__init__(x, y, color) self._size = size @property def size(self): return self._size def draw(self, screen): """ 画蛇的节点,其中,位置,由左上的位置坐标和宽高组成。0,表示实心。 :param screen: :return: """ pygame.draw.rect(screen, self._color, [self._x, self._y, self._size, self._size], 0) pygame.draw.rect(screen, BLACK_COLOR, [self._x, self._y, self._size, self._size], 1) class Snake(GameObject): def __init__(self): """由蛇节组成🐍""" super(Snake, self).__init__() self._dir = LEFT self._nodes = [] self._alive = True for index in range(5): node = SnakeNode(290 + index * 20, 250, 20) self._nodes.append(node) @property def head(self): return self._nodes[0] @property def dir(self): return self._dir @property def alive(self): return self._alive def collide(self, wall): """撞到墙返回真,否则返回False""" head = self.head if head.x < wall.x or head.x + head.size > wall.x + wall.width\ or head.y < wall.y or head.y + head.size > wall.y + wall.height: self._alive = False def eat_food(self, food): if self.head.x == food.x and self.head.y == food.y: tail = self._nodes[-1] self._nodes.append(tail) return True return False def draw(self, screen): for node in self._nodes: node.draw(screen) def move(self): if self._alive: snake_dir = self._dir x, y, size = self.head.x, self.head.y, self.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 change_dir(self, new_dir): if (self._dir + new_dir) % 2 != 0: self._dir = new_dir class Wall(GameObject): def __init__(self, x, y, width, height, color=BLACK_COLOR): super(Wall, self).__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) class Food(GameObject): def __init__(self, x, y, size, color=FOOD_COLOR): super(Food, self).__init__(x, y, color) self._size = size self._hidden = False def draw(self, screen): """让食物闪烁起来""" if not self._hidden: pygame.draw.circle(screen, self._color, (self._x + self._size // 2, self._y + self._size // 2), self._size // 2, 0) self._hidden = not self._hidden def main(): def refresh(): """刷新游戏窗口""" screen.fill([242, 242, 242]) snake.draw(screen) wall.draw(screen) food.draw(screen) pygame.display.flip() def handle_key_event(key_event): """接受按键事件""" key = key_event.key if key == pygame.K_F2: reset_game() else: if snake.alive: new_dir = snake.dir if key == pygame.K_w: new_dir = UP elif key == pygame.K_d: new_dir = RIGHT elif key == pygame.K_s: new_dir = DOWN elif key == pygame.K_a: new_dir = LEFT if new_dir != snake.dir: snake.change_dir(new_dir) def create_food(): row = randint(0, 29) col = randint(0, 29) return Food(10 + 20 * row, 10 + 20 * col, 20) def reset_game(): nonlocal food, snake food = create_food() snake = Snake() wall = Wall(10, 10, 600, 600) food = create_food() snake = Snake() pygame.init() pygame.display.set_caption('贪吃蛇') screen = pygame.display.set_mode([620, 620]) # 左上角是坐标原点。 screen.fill([242, 242, 242]) pygame.display.flip() 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.KEYDOWN: handle_key_event(event) # 调用按键函数 if snake.alive: refresh() # 调用刷新函数 clock.tick(10) # 刷新次数 if snake.alive: snake.move() snake.collide(wall) if snake.eat_food(food): food = create_food() pygame.quit() if __name__ == '__main__': main()
分子分母的重写
from math import gcd class Fraction(object): def __init__(self, num=1, den=1): # 后面跟两个下划线,是共有的,如果后面有一个或没有,才是私有的。 """ 分子分母 :param num:分子 :param den: 分母 """ if den == 0: raise ValueError('分母不能为零') # 你敢让他为零,我就死给你看 self._num = num self._den = den self.normalize() # 自动调用正常化 self.simplify() # 自动调用化简 @property def num(self): return self._num # @num.setter # def num(self, num): # self._num = num @property def den(self): return self._den # @den.setter # def den(self, den): # self._den = den def add(self, other): """加法""" return Fraction(self._num * other.den + self._den * other.num, self._den * other.den) def __add__(self, other): """运算符重载/重写""" return self.add(other) def sub(self, other): """减法""" return Fraction(self._num * other.den - self._den * other.num, self._den * other.den) def __sub__(self, other): return self.sub(other) def mul(self, other): """乘法""" return Fraction(self._num * other.num , self._den * other.den) def __mul__(self, other): return self.mul(other) def truediv(self, other): """除法""" return Fraction(self._num * other.den , self._den * other.num) def __truediv__(self, other): return self.truediv(other) def simplify(self): """ 化简 :return: """ if self._num != 0 and self._den != 1: factor = gcd(abs(self._num), abs(self._den)) if factor > 1: self._den //= factor self._num //= factor def normalize(self): """ 正规化 :return: """ if self._den < 0: self._num = -self._num self._den = -self._den 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(-1, -3) f2 = Fraction(4, 2) f3 = Fraction(0, 4) print(f1 + f2) print(f2 - f1) print(f3 * f1) 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 = [[]] * 15 self.reset() def reset(self): """重置棋盘""" for row in range(len(self._board)): self._board[row] = [EMPTY] * 15 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): """ 画棋盘,天元,四点,画棋子 :param screen: :return: """ for i in range(1, 16): pygame.draw.line(screen, black_color, [40, i * 40], [600, i * 40], 1) # 画行 pygame.draw.line(screen, black_color, [i * 40, 40], [i * 40, 600], 1) # 画列 pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4) # 画边框 pygame.draw.circle(screen, black_color, [320, 320], 5, 0) # 坐标,半径,0是实心,1是圆周的粗细 pygame.draw.circle(screen, black_color, [160, 160], 5, 0) pygame.draw.circle(screen, black_color, [480, 480], 5, 0) pygame.draw.circle(screen, black_color, [160, 480], 5, 0) pygame.draw.circle(screen, black_color, [480, 160], 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, 18, 0) def main(): 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 = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYUP: board.reset() elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: x, y = event.pos 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) pygame.display.flip() pygame.quit() if __name__ == '__main__': main()
打球吃小球
from random import randint import pygame class Ball(object): def __init__(self, center, color, radius, sx, sy): self._center = center self._color = color self._radius = radius self._sx = sx self._sy = sy @property def center(self): return self._center @property def radius(self): return self._radius def move(self): """移动后的坐标""" x, y = self._center[0], self._center[1] x += self._sx y += self._sy self._center = (x, y) if (x + self._radius >= 800 and self._sx > 0) or (x - self._radius <= 0 and self._sx < 0): self._sx = -self._sx if (y + self._radius >= 600 and self._sy > 0) or (y - self._radius <= 0 and self._sy < 0): self._sy = - self._sy def eat(self, other): pass def draw(self, screen): """画一个圆""" pygame.draw.circle(screen, self._color, self._center, self._radius, 0) def refresh(screen, balls): bg_color = (242, 242, 242) 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 def main(): pygame.init() balls = [] 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: # = event.pos color = random_color() radius = randint(10, 100) sx, sy = randint(-10, 10), randint(-10, 10) ball = Ball(event.pos, color, radius, sx, sy) balls.append(ball) refresh(screen, balls) clock.tick(20) for ball in balls: ball.move() pygame.quit() if __name__ == '__main__': main()