__len__和__getitem__
作者:互联网
import collections
import random
Card = collections.namedtuple("Card", ["rank", "suit"])
class FrenchDeck:
ranks = ["A"] + [str(n) for n in range(2, 11)] + list("JQK")
suits = "红桃 方块 黑桃 梅花".split()
def __init__(self):
self._cards = [Card(rank=rank, suit=suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
# 此方法对应了[]获取属性
# 因为把[]操作交给了一个列表,所以支持切片,以及实现了random.choice,以及实现了迭代
return self._cards[item]
# 通过实现特殊方法来利用Python数据模型有两个显而易见的好处
# 1.作为你的类的用户,他们不必去记住标准操作的各式名称.
# 2.可以更加方便的利用Python的标准库
deck = FrenchDeck()
print(deck[:3]) # 查看前三张牌
print(deck[::13]) # 只看牌面是A的牌
print(random.choice(deck))
# 仅仅实现了__getitem__方法,就变成可迭代的了
for card in deck:
print(card)
# 反向迭代也没有问题
for card in reversed(deck):
print(card)
# 迭代通常是隐式的,譬如说一个集合类型没有实现__contains__方法,那么in运算符就会按顺序做一次迭代搜索
print(Card(rank="A", suit="黑桃") in deck)
print(Card(rank="B", suit="黑桃") in deck)
# 纸牌排序 我们按照A最小K最大来,先按牌面排序然后按花色排序. 黑桃最大,梅花最小.
suit_values = dict(黑桃=3, 红桃=2, 方块=1, 梅花=0) # 构建一个花色权重字典{'黑桃': 3, '红桃': 2, '方块': 1, '梅花': 0}
def spades_high(card_: Card):
rank_value = FrenchDeck.ranks.index(card_.rank) # 0-12
return rank_value * len(suit_values) + suit_values[card_.suit]
for card in sorted(deck, key=spades_high):
print(card)
# 这里留下一个思考,如何在不破坏类的封装性的基础上,实现洗牌.
标签:__,deck,len,rank,getitem,suit,print,card 来源: https://www.cnblogs.com/zyyhxbs/p/13131901.html