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列表。

原文地址:https://www.cnblogs.com/xiximayou/p/12164274.html

时间: 2024-10-14 14:04:30

python之使用魔术方法__getitem__和__len__的相关文章

Python 类的魔术方法

Python中类的魔术方法 在Python中以两个下划线开头的方法,__init__.__str__.__doc__.__new__等,被称为"魔术方法"(Magic methods).魔术方法在类或对象的某些事件出发后会自动执行,如果希望根据自己的程序定制自己特殊功能的类,那么就需要对这些方法进行重写. 注意:Python 将所有以 __(两个下划线)开头的类方法保留为魔术方法.所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀. Python提供的魔术方法 魔术方法这里

python中类的魔术方法

目的:学习python中class的magic methods,提高编程效率. 环境:ubuntu 16.4   python 3.5.2 在学习class是一定会接触到它的magic methods,比如常用__init__,形式都是前后有双下划线.除了这个必须的,还有其他有用的方法,下面大概的介绍一下. 运算魔法方法: __add__ 用作 + __sub__ 用作 - __mul__ 用作 * __truediv__用作/ __floordiv__用作// __mod__用作% __pow

流动python - 什么是魔术方法(magic method)

我们经常看到各种各样的方法已经被包围了由双下划线,例如__init__,他们是魔术方法. 魔术方法python语言预订好"协议",在不同情况下不同的魔术方法,是隐式调用.我们重写这些方法,因此,操纵各种行为. class A(object): def __str__(self): return "I am A,2333" def __len__(self): return 42 a = A() print a#输出 "I am A,2333" p

飘逸的python - 什么是魔术方法(magic method)

我们经常看到各种被双下划线环绕的方法,如__init__,它们就是魔术方法. 魔术方法是python语言预定好的"协议",不同魔术方法在不同场景下,会被隐式调用.我们通过重载这些方法,从而操控各种行为. class A(object): def __str__(self): return "I am A,2333" def __len__(self): return 42 a = A() print a#输出 "I am A,2333" prin

【python基础】魔术方法

魔术方法:就是类中的方法(预定义的方法),在某个特定的时机会被自动的调用. 1.__del__():销毁对象时,被自动的调用 1 class Person: 2 def __init__(self, name): 3 self.name = name 4 print('%s 被初始化' % self.name) 5 6 def __del__(self): 7 print("%s 被删除 " % self.name) 8 9 10 p1 = Person("奶茶")

Python 类特殊方法__getitem__如何使用?

本文和大家分享的主要是python类的特殊方法__getitem__相关内容,一起来看看吧,希望对大家学习python有所帮助. 凡是在类中定义了这个__getitem__ 方法,那么它的实例对象(假定为p),可以像这样 p[key] 取值,当实例对象做p[key] 运算时,会调用类中的方法__getitem__. 先用一个夸张一点的例子来说明这个问题. 当实例对象通过[] 运算符取值时,会调用它的方法__getitem__,从上面代码中输出二个笑脸可以看出来. 一般这样用 ''' 黄哥Pyth

pyhton中的魔术方法

魔术方法 ***** 特殊属性 属性 说明 __name__ 类.函数.方法等的名字 __module__ 类定义所在的模块名 __class__ 对象或类所属的类 __bases__ 类的基类的元组,顺序为它们在基类列表中出现的顺序 __doc__ 类.函数的文档字符串,如果没有定义则为 None __mro__ 类的mro,class.mro()返回的结果的保存在 __mro__ 中 __dict__ 类或实例的属性,可写的字典 查看属性 __dir__ 方法 方法 说明 __dir__ 返

Python 魔术方法笔记

魔术方法总是被__包围, 如__init__ , __len__都是常见的魔术方法,这里主要写一下我遇到的一些魔术方法 setitem 对某个索引值赋值时 即可以进行赋值操作,如 def __setitem__(self, k, v): self.put(k, v) 在上述代码的情况下,可以执行p['key'] = value操作,即将key赋给k,value赋给v,执行put(k, v)函数.所以,__setitem__建立的前提,是要这个函数内的操作本来具有赋值的性质. getitem 使用

Python中类的特殊属性和魔术方法

1.属性 属性 含义 __name__ 类.函数.方法等的名字   __dir__ __module__ 类定义所在的模块名 __class__ 对象或类所属的类   只是返回基类 __bases__ 返回自己到object的类,类的基类元组,顺序为在基类列表中出现的顺序. __doc__ 类,函数的文档字符串,如果没有定义则为None. __mro__ 类的不是实例的.类的mro,class.mro()返回的结果保存在__mro__中. __dict__ 类或实例属性,可写的字典. 标识符和名