从零开始重新学python第11天--面向对象

面向对象相关知识

三大支柱:封装、继承、多态

例子:工资结算系统。

"""
月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成
"""
from abc import ABCMeta, abstractmethod


class Employee(metaclass=ABCMeta):
    """员工(抽象类)"""

    def __init__(self, name):
        self.name = name

    @abstractmethod
    def get_salary(self):
        """结算月薪(抽象方法)"""
        pass


class Manager(Employee):
    """部门经理"""

    def get_salary(self):
        return 15000.0


class Programmer(Employee):
    """程序员"""

    def __init__(self, name, working_hour=0):
        self.working_hour = working_hour
        super().__init__(name)

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


class Salesman(Employee):
    """销售员"""

    def __init__(self, name, sales=0.0):
        self.sales = sales
        super().__init__(name)

    def get_salary(self):
        return 1800.0 + self.sales * 0.05


class EmployeeFactory:
    """创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)"""

    @staticmethod
    def create(emp_type, *args, **kwargs):
        """创建员工"""
        all_emp_types = {'M': Manager, 'P': Programmer, 'S': Salesman}
        cls = all_emp_types[emp_type.upper()]
        return cls(*args, **kwargs) if cls else None


def main():
    """主函数"""
    emps = [
        EmployeeFactory.create('M', '曹操'), 
        EmployeeFactory.create('P', '荀彧', 120),
        EmployeeFactory.create('P', '郭嘉', 85), 
        EmployeeFactory.create('S', '典韦', 123000),
    ]
    for emp in emps:
        print(f'{emp.name}: {emp.get_salary():.2f}元')


if __name__ == '__main__':
    main()
  • @staticmethod:定义不依赖于类实例或类状态的静态方法。
  • @abstractmethod:定义抽象基类中的抽象方法,要求子类实现这些方法。

通过工厂模式,客户端代码无需知道具体的类名和构造函数细节,只需提供所需对象的类型,工厂类会负责创建并返回相应的对象。 

单一职责原则:

对象创建的逻辑集中在工厂类中,客户端代码只负责使用对象。这符合单一职责原则(Single Responsibility Principle),使代码结构更加清晰。不使用工厂模式的话客户端代码既负责创建对象又负责使用对象,职责不单一,增加了代码的复杂性。

例子:扑克游戏。

"""
经验:符号常量总是优于字面常量,枚举类型是定义符号常量的最佳选择
"""
from enum import Enum, unique

import random


@unique
class Suite(Enum):
    """花色"""

    SPADE, HEART, CLUB, DIAMOND = range(4)

    def __lt__(self, other):
        return self.value < other.value


class Card:
    """牌"""

    def __init__(self, suite, face):
        """初始化方法"""
        self.suite = suite
        self.face = face

    def show(self):
        """显示牌面"""
        suites = ['♠︎', '♥︎', '♣︎', '♦︎']
        faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
        return f'{suites[self.suite.value]}{faces[self.face]}'

    def __repr__(self):
        return self.show()


class Poker:
    """扑克"""

    def __init__(self):
        self.index = 0
        self.cards = [Card(suite, face)
                      for suite in Suite
                      for face in range(1, 14)]

    def shuffle(self):
        """洗牌(随机乱序)"""
        random.shuffle(self.cards)
        self.index = 0

    def deal(self):
        """发牌"""
        card = self.cards[self.index]
        self.index += 1
        return card

    @property
    def has_more(self):
        return self.index < len(self.cards)


class Player:
    """玩家"""

    def __init__(self, name):
        self.name = name
        self.cards = []

    def get_one(self, card):
        """摸一张牌"""
        self.cards.append(card)

    def sort(self, comp=lambda card: (card.suite, card.face)):
        """整理手上的牌"""
        self.cards.sort(key=comp)


def main():
    """主函数"""
    poker = Poker()
    poker.shuffle()
    players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')]
    while poker.has_more:
        for player in players:
                player.get_one(poker.deal())
    for player in players:
        player.sort()
        print(player.name, end=': ')
        print(player.cards)


if __name__ == '__main__':
    main()

 继承 Enum 表示定义一个枚举类。枚举(Enumeration)是一个包含一组名称和值对的集合,每个成员都是唯一的常量。通过继承 Enum 类,我们可以创建一组有意义的常量,通常用于表示一组相关的常量值,如一副牌中的花色或一周中的天数。

@unique 是一个装饰器,用于确保枚举类中的值是唯一的。如果枚举类中存在重复的值,@unique 会抛出 ValueError 异常。这对于防止枚举类中的成员具有相同的值非常有用。

__lt__ 方法是 Python 的特殊方法之一,用于实现小于比较运算符 <。在枚举类中定义 __lt__ 方法,可以自定义两个枚举成员之间的比较规则。

在 Python 中,特殊方法(或魔术方法)是以双下划线开头和结尾的方法,用于实现特定的操作行为。__lt__ 方法是其中之一,用于实现小于比较运算符 <。当你在对象上使用 < 运算符时,Python 会调用该对象的 __lt__ 方法。

key=comp 指定了排序的键函数。在这里,comp 是一个匿名函数 lambda card: (card.suite, card.face),它将每张牌转换为一个包含 suiteface 的元组。Python 将使用这些元组进行排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值