细数Python的特殊方法一:集合类
1. 特殊方法汇总列表
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__方法