细数Python的特殊方法一:集合类

时间:2022-06-19 17:02:08

1. 特殊方法汇总列表

 

细数Python的特殊方法一:集合类

 

2. 仿集合类

__len__:返回对象的长度

__getitem__:获得某一项的值

__setitem__:设置莫一项的值

__delitem__删除某一项

__contains__:包含某一项

 

实现说明:

1) 模拟一副扑克牌,包含两个类,一个是卡片类(Card),一个是 扑克(PuKe),PuKe类包含52张牌,13个大小(AJQK,2-10),4张花色("redheart", "spades", "diamond", "club").

2) 卡片类包含两个属性,rank(等级)、color(花色),以及重写了__eq__方法,判断卡片的相同性,为后续PuKe类中的__getitem__,__setitem__方法中的判断做铺垫;

3) 实现PuKe中的__len__,__getitem__,__setitem__,__contains__等方法。

代码实现:

Card类代码如下:

class Card:
def __init__(self, rank, color):
self.rank = rank
self.color = color
def __repr__(self):
return "Card rank is %s and color is %s" % (self.rank, self.color)

def __eq__(self, other):
if isinstance(other, (tuple, )):
if self.rank == other[0] and self.color == other[1]:
return True
if isinstance(other, (Card,)):
if self.rank == other.rank and self.color == other.color:
return True

return False

说明:

1) __init__方法包含两个属性,rank和color

2) 重写__repr__方法,格式化后续的Card类对象的打印信息

3) 重写__eq__方法,只有rank、color两个属性都满足的情况下,才能判断卡片是相同的。

PuKe类的实现:

class PuKe:
ranks = [str(rank) for rank in range(2, 11)] + list("JQKA")
colors = ["redheart", "spades", "diamond", "club"]

def __init__(self):
"""
初始化生成牌
"""
self._cards = [Card(rank, color) for rank in PuKe.ranks
for color in PuKe.colors]

def __len__(self):
"""
返回一副扑克中牌的张数
:return:
"""

return len(self._cards)

def __getitem__(self, item):
"""
获得某一张牌
:param item:
:return:
"""
assert item is not None
result = None
if isinstance(item, (int,)):
result = self._cards[item]
elif isinstance(item, (tuple,)):
result = []
for card in self._cards:
if card == item:
return card

return result

def __setitem__(self, key, value):
"""
设置某一项的值
:param key: rank+color,为一元组
:param value: other rank+color,元组
:return: void
"""
assert key is not None
if not isinstance(key, (tuple,)) or not isinstance(value, (tuple,)):
return
for card in self._cards:
if card == key:
card.rank = value[0]
card.color = value[1]
return
def __contains__(self, item):
"""
判断是否包含一个牌
:param item: 元组
:return:
"""
for card in self._cards:
if card == item:
return True
return False

 

说明:

1) __init__方法,初始化52中卡片

2) __len__方法,返回卡片的数量,肯定等于52

3) 在__getitem__方法的实现中,两种实现方法来获得某一张卡片,一个是根据索引号,一个是根据卡片的rank和color属性来定位一张卡片。

4) __setitem__方法中,key是rank和color的元组,实现卡片的定位

5) __contains__方法,判断卡片是否在扑克牌中。

 

代码测试:

if __name__ == '__main__':

puke1 = PuKe()
print("一副牌的张数为%d " % len(puke1))
print("牌分别为:")
#循环,同样会调用__getitem__
for card in puke1:
print(card)

card5 = puke1[5]
print("第5张牌的rank为%s,花色为:%s" % (card5.rank, card5.color))

cardA = puke1[("A", "spades")]
print("A牌的花色分别为:%s" % cardA.color)


print("随机选张牌")
from random import choice

# 随机选择,同样会调用__getitem__
card = choice(puke1)
print(card)

#会调用__setitem__方法
puke1[("7", "spades")] = ("7", "gagagwer")
#再次打印puke
for card in puke1:
print(card)
#会调用__container__方法
print(("7", "gagagwer") in puke1)

 

总结:循环会调用__getitem__,如果某个对象要能循环,必须具备___getitem__方法