面向对象练习


本章概述:python基础——面向对象练习


1、制作扑克

说明:一幅扑克有52张牌(除大小王),我们需要实现随机抽取扑克牌的功能。

使用面向对象编程方法,首先需要从问题的需求中找到对象并抽象出对应的类,此外还要找到对象的属性和行为。我们可以从需求的描述中找出名词和动词,名词通常就是对象或者是对象的属性,而动词通常是对象的行为。所以上面的说明至少有两个对象,分别为扑克和扑克牌,扑克有随机抽取的功能。一幅扑克有52张牌,扑克牌有两个属性,分别为大小跟花色,并且一幅扑克的每张牌都是这样,因此我们可以把定义一个扑克牌类,然后再定义扑克类,首先定义扑克牌类。

1
2
3
4
5
6
7
8
9
10
11
class Card:

def __init__(self, rand, suit):
self.rand = rand # 大小
self.suit = suit # 花色

def __repr__(self):
return f'{self.suit}{self.rand}'

card1 = Card('5', '黑桃')
print(card1) #黑桃5

接下来定义扑克类

1
2
3
4
5
6
7
8
9
import random
class Poker:
rands = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
# 黑桃,方块,梅花,红桃,并且按照从小到大排序
suits = ['方块', '梅花', '红桃', '黑桃']

def __init__(self):
# 定义52张牌
self.__cards = [Card(rand, suit) for rand in self.rands for suit in self.suits]

实现扑克具体的行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Poker:
rands = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
# 黑桃,方块,梅花,红桃,并且按照从小到大排序
suits = ['方块', '梅花', '红桃', '黑桃']

def __init__(self):
# 定义52张牌
self.__cards = [Card(rand, suit) for rand in self.rands for suit in self.suits]

# 实现len()函数
def __len__(self):
return len(self.__cards)

# 随机抽取一张
def get(self):
return random.choice(self.__cards)

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

1
2
3
poker=Poker()
print(len(poker)) #52
print(poker.get()) #红桃J

上面的代码只实现了扑克的两种行为,实际上如果想实现一些扑克游戏功能,则扑克还需要更多的行为,比如发牌行为、洗牌行为等等,扑克牌类比如还需要比较大小的行为。现在为扑克牌类新增一个比较大小的函数,但是我们需要比较的是两个对象的大小,而普通的比较运算符不能直接作用于Card类型,因此我们需要对运算符进行重载,这里我们只重载<符号,重载小于号用到的特殊方法是__lt__,上一篇博客有提到一些特殊方法,可以去看一看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Card:

def __init__(self, rand, suit):
self.rand = rand # 大小
self.suit = suit # 花色

def __repr__(self):

return f'{self.suit}{self.rand}'

def __lt__(self, other):
# 同大小的比较花色
if Poker.rands.index(self.rand) == Poker.rands.index(other.rand):
return Poker.suits.index(self.suit) < Poker.suits.index(other.suit)

return Poker.rands.index(self.rand) < Poker.rands.index(other.rand)

通过以下代码进行测试

1
2
3
4
c1=Card('J','红桃')
c2=Card('J','方块')
print(c1<c2) #False
print(poker.get()<poker.get()) #True

实际上,重载了__lt__方法后,实际上也可以实现大于号预算,同样的道理,如果想实现==或!=运算,只需要实现这两种特殊方法的一种即可,<=或>=也是如此。