python之使用魔术方法__getitem__和__len__
Posted 西西嘛呦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之使用魔术方法__getitem__和__len__相关的知识,希望对你有一定的参考价值。
(1)像__getitem__这种由两个双下划线构成的方法,被称为魔术方法。
(2)魔术方法是为了给python解释器用的。当使用len(collection)时,实际上调用的就是collection.__len__方法。而在使用obj[key]的形式来访问元素时,实际上调用的是object.__getitem__(key)方法。
(3)魔术方法是属于类的方法,也就是说不需要实例化类就可以访问到该方法,同时,实例化的对象都可以访问到该方法。
(4)使用__getitem__和__len__方法,我们就可以实现一个对自定义数据类型的迭代和访问。
举个例子:
import collections Card = collections.namedtuple("Card",["rank","suit"]) class FrenchDeck(object): ranks = [str(n) for n in range(2,11)] + list("JQKA") #黑桃 方块 红桃 梅花 suits = "spades diamonds hearts clubs ".split() def __init__(self): self._cards = [Card(rank,suit) for rank in self.ranks for suit in self.suits] def __getitem__(self, item): return self._cards[item] def __len__(self): return len(self._cards)
说明:
- Card = collections.namedtuple("Card",["rank","suit"])创建一个名字为Card的类,并且具有属性rank和suit,rank表示牌的数值,suit表示牌的花色。
- 一个FrenchDeck类,用于生成52张扑克牌,从2-A,红桃、方块、红桃、梅花。ranks、suits以及魔术方法都是类方法。
首先说明的是类属性和方法,直接用类名.属性或类名.方法访问即可。
print(FrenchDeck.ranks) print(FrenchDeck.suits) print(FrenchDeck.__len__(FrenchDeck()))
输出:
自定义的FrenchDeck类在重写了__getitem__和__len__方法之后,就可以对FrenchDeck实例化的对象进行类似于列表的操作。
1.得到对象的长度
deck = FrenchDeck() print(len(deck))
输出:52
2.通过下标来获列表元素
print(deck[0]) print(deck[-1])
输出:
Card(rank=\'2\', suit=\'spades\')
Card(rank=\'A\', suit=\'clubs\')
3.对列表进行遍历。当然也可以使用reversed方法进行翻转遍历
for d in reversed(deck): print(d)
输出:
Card(rank=\'A\', suit=\'clubs\')
Card(rank=\'A\', suit=\'hearts\')
Card(rank=\'A\', suit=\'diamonds\')
Card(rank=\'A\', suit=\'spades\')
Card(rank=\'K\', suit=\'clubs\')
Card(rank=\'K\', suit=\'hearts\')
Card(rank=\'K\', suit=\'diamonds\')
Card(rank=\'K\', suit=\'spades\')
Card(rank=\'Q\', suit=\'clubs\')
Card(rank=\'Q\', suit=\'hearts\')
Card(rank=\'Q\', suit=\'diamonds\')
Card(rank=\'Q\', suit=\'spades\')
Card(rank=\'J\', suit=\'clubs\')
Card(rank=\'J\', suit=\'hearts\')
Card(rank=\'J\', suit=\'diamonds\')
Card(rank=\'J\', suit=\'spades\')
Card(rank=\'10\', suit=\'clubs\')
Card(rank=\'10\', suit=\'hearts\')
Card(rank=\'10\', suit=\'diamonds\')
Card(rank=\'10\', suit=\'spades\')
Card(rank=\'9\', suit=\'clubs\')
Card(rank=\'9\', suit=\'hearts\')
Card(rank=\'9\', suit=\'diamonds\')
Card(rank=\'9\', suit=\'spades\')
Card(rank=\'8\', suit=\'clubs\')
Card(rank=\'8\', suit=\'hearts\')
Card(rank=\'8\', suit=\'diamonds\')
Card(rank=\'8\', suit=\'spades\')
Card(rank=\'7\', suit=\'clubs\')
Card(rank=\'7\', suit=\'hearts\')
Card(rank=\'7\', suit=\'diamonds\')
Card(rank=\'7\', suit=\'spades\')
Card(rank=\'6\', suit=\'clubs\')
Card(rank=\'6\', suit=\'hearts\')
Card(rank=\'6\', suit=\'diamonds\')
Card(rank=\'6\', suit=\'spades\')
Card(rank=\'5\', suit=\'clubs\')
Card(rank=\'5\', suit=\'hearts\')
Card(rank=\'5\', suit=\'diamonds\')
Card(rank=\'5\', suit=\'spades\')
Card(rank=\'4\', suit=\'clubs\')
Card(rank=\'4\', suit=\'hearts\')
Card(rank=\'4\', suit=\'diamonds\')
Card(rank=\'4\', suit=\'spades\')
Card(rank=\'3\', suit=\'clubs\')
Card(rank=\'3\', suit=\'hearts\')
Card(rank=\'3\', suit=\'diamonds\')
Card(rank=\'3\', suit=\'spades\')
Card(rank=\'2\', suit=\'clubs\')
Card(rank=\'2\', suit=\'hearts\')
Card(rank=\'2\', suit=\'diamonds\')
Card(rank=\'2\', suit=\'spades\')
4.使用choice随机抽取一张牌
from random import choice print(choice(deck))
5.利用in判断一张牌是否在对象列表中
print(Card("Q","clubs") in deck)
6.可以对牌组进行排序,按照花色桃心梅方以及数值大小
def spades_high(card): #首先得到该卡牌在数值中的位置 rank_value = FrenchDeck.ranks.index(card.rank) #返回的是其位置*4+花色对应的级别 #比如梅花2的大小为0,黑桃A的大小为12*4+3=51 return rank_value*len(suit_values)+suit_values[card.suit] #Card = Card("A","spades") #print(spades_high(Card)) 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=\'3\', suit=\'diamonds\')
Card(rank=\'3\', suit=\'clubs\')
Card(rank=\'3\', suit=\'hearts\')
Card(rank=\'3\', suit=\'spades\')
Card(rank=\'4\', suit=\'diamonds\')
Card(rank=\'4\', suit=\'clubs\')
Card(rank=\'4\', suit=\'hearts\')
Card(rank=\'4\', suit=\'spades\')
Card(rank=\'5\', suit=\'diamonds\')
Card(rank=\'5\', suit=\'clubs\')
Card(rank=\'5\', suit=\'hearts\')
Card(rank=\'5\', suit=\'spades\')
Card(rank=\'6\', suit=\'diamonds\')
Card(rank=\'6\', suit=\'clubs\')
Card(rank=\'6\', suit=\'hearts\')
Card(rank=\'6\', suit=\'spades\')
Card(rank=\'7\', suit=\'diamonds\')
Card(rank=\'7\', suit=\'clubs\')
Card(rank=\'7\', suit=\'hearts\')
Card(rank=\'7\', suit=\'spades\')
Card(rank=\'8\', suit=\'diamonds\')
Card(rank=\'8\', suit=\'clubs\')
Card(rank=\'8\', suit=\'hearts\')
Card(rank=\'8\', suit=\'spades\')
Card(rank=\'9\', suit=\'diamonds\')
Card(rank=\'9\', suit=\'clubs\')
Card(rank=\'9\', suit=\'hearts\')
Card(rank=\'9\', suit=\'spades\')
Card(rank=\'10\', suit=\'diamonds\')
Card(rank=\'10\', suit=\'clubs\')
Card(rank=\'10\', suit=\'hearts\')
Card(rank=\'10\', suit=\'spades\')
Card(rank=\'J\', suit=\'diamonds\')
Card(rank=\'J\', suit=\'clubs\')
Card(rank=\'J\', suit=\'hearts\')
Card(rank=\'J\', suit=\'spades\')
Card(rank=\'Q\', suit=\'diamonds\')
Card(rank=\'Q\', suit=\'clubs\')
Card(rank=\'Q\', suit=\'hearts\')
Card(rank=\'Q\', suit=\'spades\')
Card(rank=\'K\', suit=\'diamonds\')
Card(rank=\'K\', suit=\'clubs\')
Card(rank=\'K\', suit=\'hearts\')
Card(rank=\'K\', suit=\'spades\')
Card(rank=\'A\', suit=\'diamonds\')
Card(rank=\'A\', suit=\'clubs\')
Card(rank=\'A\', suit=\'hearts\')
Card(rank=\'A\', suit=\'spades\')
说了这么多,就是为了说明通过实现__getitem__和__len__方法,FrenchDeck就和一个python自有的序列数据类型一样了。对合成的运用使得__len__和__getitem__的具体实现可以代理给self._card这个python列表。
以上是关于python之使用魔术方法__getitem__和__len__的主要内容,如果未能解决你的问题,请参考以下文章
python 魔法方法之:__getitem__ __setitem__ __delitem__