加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python之使用魔术方法__getitem__和__len__

发布时间:2020-12-20 09:52:29 所属栏目:Python 来源:网络整理
导读:(1)像__getitem__这种由两个双下划线构成的方法,被称为魔术方法。 (2)魔术方法是为了给python解释器用的。当使用len(collection)时,实际上调用的就是collection.__len__方法。而在使用obj[key]的形式来访问元素时,实际上调用的是object.__getitem__(k

(1)像__getitem__这种由两个双下划线构成的方法,被称为魔术方法。

(2)魔术方法是为了给python解释器用的。当使用len(collection)时,实际上调用的就是collection.__len__方法。而在使用obj[key]的形式来访问元素时,实际上调用的是object.__getitem__(key)方法。

(3)魔术方法是属于类的方法,也就是说不需要实例化类就可以访问到该方法,同时,实例化的对象都可以访问到该方法。

(4)使用__getitem__和__len__方法,我们就可以实现一个对自定义数据类型的迭代和访问。

举个例子:

import collections
Card = collections.namedtuple("Card",[ranksuit"])
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  self.suits]
    __getitem__(self,item):
        return self._cards[item]
    __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)
(FrenchDeck.suits)
print(FrenchDeck.__len__(FrenchDeck()))

输出:

自定义的FrenchDeck类在重写了__getitem__和__len__方法之后,就可以对FrenchDeck实例化的对象进行类似于列表的操作。

1.得到对象的长度

deck = FrenchDeck()
print(len(deck))

输出:52

2.通过下标来获列表元素

(deck[0])
print(deck[-1])

输出:

Card(rank='2',suit='spades')
Card(rank='A',suit='clubs')

3.对列表进行遍历。当然也可以使用reversed方法进行翻转遍历

for d  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  choice
print(choice(deck))

5.利用in判断一张牌是否在对象列表中

print(Card(Qclubs") 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='spades')

说了这么多,就是为了说明通过实现__getitem__和__len__方法,FrenchDeck就和一个python自有的序列数据类型一样了。对合成的运用使得__len__和__getitem__的具体实现可以代理给self._card这个python列表

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读