Python特殊方法的作用示例说明 具名元组的运用

魔术方法(magic method)是特殊方法的昵称,在Python中的特殊方法,一般都是使用诸如__xxx__(前后两个下划线,中间是方法名)的命名方式,在书里有个名词也可以形容它,比如__getitem__,叫做“双下—getitem” (dunnder-getitem)

万事开头难
难以用概念去概括Python特殊方法的作用,最简单的方法就是用例子说明。

很多人都会选择使用Python作为快速开发工具,而特殊方法是属于“快速”这个性质。

在Python中,要拿到一个集合的某个元素,可以使用对应的引索进行取值,比如list[key],这背后利用的是__getitem__方法,为了拿到my_list[key]的值,解释器实际上会调用my_list.getitem(key)。

Python也是面向对象编程语言,对于求一个集合的长度使用len(list)而不是list.len()会感觉有点奇怪,背后就是特殊方法的作用,调用了list.len()方法,和面向对象完全符合,而且还起到简化的作用,变得更加通俗易懂。

一个完整的例子
代码
import collections

Card = collections.namedtuple(‘Card’,[‘rank’, ‘suit’]) # 具名元组

class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list(‘JQKA’) # 牌数
suits = ‘spades hearts clubs diamonds’.split() # 牌色

def __init__(self):                            # 初始化(构造函数)
    self._cards = [Card(rank, suit) for suit in self.suits
                                    for rank in self.ranks]

def __len__(self):                             # 用len取长度的特殊方法
    return len(self._cards)

def __getitem__(self, position):               # 用引索取值的特殊方法
    return self._cards[position]

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

deck = FrenchDeck()
len(deck)
52

deck[0]
Card(rank=‘2’, suit=‘spades’)
1
2
3
4
5
随机抽牌
那么我们可以使用random模块里面的一个方法随机抽取一张牌

from random import choice
choice(deck)
Card(rank=‘2’, suit=‘clubs’)

choice(deck)
Card(rank=‘J’, suit=‘clubs’)
1
2
3
4
5
切片操作
既然我们实现了引索中括号[]操作,那么我们也可以使用切片操作:

deck[:3]
[Card(rank=‘2’, suit=‘spades’), Card(rank=‘3’, suit=‘spades’),
Card(rank=‘4’, suit=‘spades’)]

deck[12::13]
[Card(rank=‘A’, suit=‘spades’), Card(rank=‘A’, suit=‘hearts’),
Card(rank=‘A’, suit=‘clubs’), Card(rank=‘A’, suit=‘diamonds’)]
1
2
3
4
5
6
迭代操作
另外,仅仅实现了__getitem__方法,那么也变成了可迭代的了:

for card in deck: # 反向迭代也可以 reversed(deck)
print(card)

Card(rank=‘2’, suit=‘spades’)
Card(rank=‘3’, suit=‘spades’)
Card(rank=‘4’, suit=‘spades’)
···
Card(rank=‘Q’, suit=‘diamonds’)
Card(rank=‘K’, suit=‘diamonds’)
Card(rank=‘A’, suit=‘diamonds’)
1
2
3
4
5
6
7
8
9
10
in运算符
如果一个集合没有实现__contains__方法,那么in运算符会按顺序做一次迭代搜索。

Card(‘A’, ‘hearts’) in deck
True

Card(‘B’, ‘hearts’) in deck
False
1
2
3
4
排序
按照扑克牌的大小,2最小,A最大,同时要加上花色的大小判定,从大到小排序:黑桃、红桃、梅花、方块。

suit_values = dict(spades = 3, hearts = 2, clubs = 1, diamonds = 0)
def spades_high(card):
rank_value = FrenchDeck.ranks.index (card.rank)
return rank_value * len(suit_values) + suit_values[card.suit]
1
2
3
4
运行

for card in sorted(deck, key = spades_high):
print(card)

Card(rank=‘2’, suit=‘diamonds’)
Card(rank=‘2’, suit=‘clubs’)
Card(rank=‘2’, suit=‘hearts’)
Card(rank=‘2’, suit=‘spades’)
···
Card(rank=‘A’, suit=‘diamonds’)
Card(rank=‘A’, suit=‘clubs’)
Card(rank=‘A’, suit=‘hearts’)
Card(rank=‘A’, suit=‘spades’)

猜你喜欢

转载自blog.csdn.net/weixin_43935079/article/details/85804910
今日推荐