Python基础篇:面向对象【案例实操】_python面向对象的实例练习 csdn

    """洗牌"""
    self.current = 0
    # 通过random模块的shuffle函数实现列表的随机乱序
    random.shuffle(self.cards)

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

@property
def has\_next(self):
    """还有没有牌可以发"""
    return self.current < len(self.cards)

![在这里插入图片描述](https://img-blog.csdnimg.cn/8ff3531906cf4adb9131d9a0c3f0caf5.png#pic_center)


* 可以通过下面的代码来测试下`Poker`类。



poker = Poker()
poker.shuffle()
print(poker.cards)


* 定义玩家类。



class Player:
“”“玩家”“”

def \_\_init\_\_(self, name):
    self.name = name
    self.cards = []

def get\_one(self, card):
    """摸牌"""
    self.cards.append(card)

def arrange(self):
    self.cards.sort()

* 创建四个玩家并将牌发到玩家的手上。



poker = Poker()
poker.shuffle()
players = [Player(‘东邪’), Player(‘西毒’), Player(‘南帝’), Player(‘北丐’)]
for _ in range(13):
for player in players:
player.get_one(poker.deal())
for player in players:
player.arrange()
print(f’{player.name}: ‘, end=’')
print(player.cards)


* 执行上面的代码会在`player.arrange()`那里出现异常,因为`Player`的`arrange`方法使用了列表的`sort`对玩家手上的牌进行排序,排序需要比较两个`Card`对象的大小,而`<`运算符又不能直接作用于`Card`类型,所以就出现了`TypeError`异常,异常消息为:`'<' not supported between instances of 'Card' and 'Card'`。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/89b63f952dc74225ade1891e07328e2c.png#pic_center)
* 为了解决这个问题,我们可以对`Card`类的代码稍作修改,使得两个`Card`对象可以直接用`<`进行大小的比较。这里用到技术叫**运算符重载**,Python中要实现对`<`运算符的重载,需要在类中添加一个名为`__lt__`的魔术方法。很显然,魔术方法`__lt__`中的`lt`是英文单词“less than”的缩写,以此类推,魔术方法`__gt__`对应`>`运算符,魔术方法`__le__`对应`<=`运算符,`__ge__`对应`>=`运算符,`__eq__`对应`==`运算符,`__ne__`对应`!=`运算符。
* 修改后的`Card`类代码如下所示。



class Card:
“”“牌”“”

def \_\_init\_\_(self, suite, face):
    self.suite = suite
    self.face = face

def \_\_repr\_\_(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 \_\_lt\_\_(self, other):
    # 花色相同比较点数的大小
    if self.suite == other.suite:
        return self.face < other.face
    # 花色不同比较花色对应的值
    return self.suite.value < other.suite.value


> 
> **说明:** 大家可以尝试在上面代码的基础上写一个简单的扑克游戏,如21点游戏(Black Jack),游戏的规则可以自己在网上找一找。
> 
> 
> 


### 经典案例2:工资结算系统。



> 
> **要求**:某公司有三种类型的员工,分别是部门经理、程序员和销售员。需要设计一个工资结算系统,根据提供的员工信息来计算员工的月薪。其中,部门经理的月薪是固定15000元;程序员按工作时间(以小时为单位)支付月薪,每小时200元;销售员的月薪由1800元底薪加上销售额5%的提成两部分构成。  
>  ![在这里插入图片描述](https://img-blog.csdnimg.cn/8b765afc52ef4edf8b55113ca7aa0941.png#pic_center)
> 
> 
> 


* 通过对上述需求的分析,可以看出部门经理、程序员、销售员都是员工,有相同的属性和行为,那么我们可以先设计一个名为`Employee`的父类,再通过继承的方式从这个父类派生出部门经理、程序员和销售员三个子类。很显然,后续的代码不会创建`Employee` 类的对象,因为我们需要的是具体的员工对象,所以这个类可以设计成专门用于继承的抽象类。Python中没有定义抽象类的关键字,但是可以通过`abc`模块中名为`ABCMeta` 的元类来定义抽象类。关于元类的知识,后面的课程中会有专门的讲解,这里不用太纠结这个概念,记住用法即可。



from abc import ABCMeta, abstractmethod

class Employee(metaclass=ABCMeta):
“”“员工”“”

def \_\_init\_\_(self, name):
    self.name = name

@abstractmethod
def get\_salary(self):
    """结算月薪"""
    pass

* 在上面的员工类中,有一个名为`get_salary`的方法用于结算月薪,但是由于还没有确定是哪一类员工,所以结算月薪虽然是员工的公共行为但这里却没有办法实现。对于暂时无法实现的方法,我们可以使用`abstractmethod`装饰器将其声明为抽象方法,所谓**抽象方法就是只有声明没有实现的方法**,**声明这个方法是为了让子类去重写这个方法**。接下来的代码展示了如何从员工类派生出部门经理、程序员、销售员这三个子类以及子类如何重写父类的抽象方法。



class Manager(Employee):
“”“部门经理”“”

def get\_salary(self):
    return 15000.0

class Programmer(Employee):
“”“程序员”“”

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

def get\_salary(self):
    return 200 \* self.working_hour

class Salesman(Employee):
“”“销售员”“”

def \_\_init\_\_(self, name, sales=0):
    super().__init__(name)
    self.sales = sales

def get\_salary(self):
    return 1800 + self.sales \* 0.05

* 上面的`Manager`、`Programmer`、`Salesman`三个类都继承自`Employee`,三个类都分别重写了`get_salary`方法。**重写就是子类对父类已有的方法重新做出实现**。相信大家已经注意到了,三个子类中的`get_salary`各不相同,所以这个方法在程序运行时会产生**多态行为**,多态简单的说就是**调用相同的方法**,**不同的子类对象做不同的事情**。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/da61009357104517b77d3ccf77e1d758.png#pic_center)
* 我们通过下面的代码来完成这个工资结算系统,由于程序员和销售员需要分别录入本月的工作时间和销售额,所以在下面的代码中我们使用了Python内置的`isinstance`函数来判断员工对象的类型。我们之前讲过的`type`函数也能识别对象的类型,但是`isinstance`函数更加强大,因为它可以判断出一个对象是不是某个继承结构下的子类型,你可以简答的理解为`type`函数是对对象类型的精准匹配,而`isinstance`函数是对对象类型的模糊匹配。



emps = [
Manager(‘刘备’), Programmer(‘诸葛亮’), Manager(‘曹操’),
Programmer(‘荀彧’), Salesman(‘吕布’), Programmer(‘张辽’),
]
for emp in emps:
if isinstance(emp, Programmer):
emp.working_hour = int(input(f’请输入{emp.name}本月工作时间: ‘))
elif isinstance(emp, Salesman):
emp.sales = float(input(f’请输入{emp.name}本月销售额: ‘))
print(f’{emp.name}本月工资为: ¥{emp.get_salary():.2f}元’)


![在这里插入图片描述](https://img-blog.csdnimg.cn/f5e9dc4afd0a4736b44fcbe4ecf2ed29.gif#pic_center)



### 最后

不知道你们用的什么环境,我一般都是用的Python3.6环境和pycharm解释器,没有软件,或者没有资料,没人解答问题,都可以免费领取(包括今天的代码),过几天我还会做个视频教程出来,有需要也可以领取~  

给大家准备的学习资料包括但不限于:  

Python 环境、pycharm编辑器/永久激活/翻译插件  

python 零基础视频教程  

Python 界面开发实战教程  

Python 爬虫实战教程  

Python 数据分析实战教程  

python 游戏开发实战教程  

Python 电子书100本  

Python 学习路线规划

![](https://img-blog.csdnimg.cn/d29631674929476f9c3b30f7ff58dff0.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlaTM0Nzc5NTc5MA==,size_16,color_FFFFFF,t_70)




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值