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列表。
- 小谈中文环境下中文排版的font-family 字体选择
- WordPress 的几个高级调试( Debug)技巧
- Customizer Library:主题“自定义”功能的WordPress类库
- Reactjs 入门基础(二)
- WordPress中当评论审核通过时候给评论者发邮件
- Reactjs 入门基础(一)
- Option Framework 框架的三个自定义技巧
- 记录一个在Mac OS X 中本地安装Ghost 的报错问题
- 盘点:2017年发生在上海的科技大新闻 与我们的生活如何密切相关
- 滚雷进口车获5亿元投资 品牌双拼给力十足
- Github 与 Bitbucket 的互助协作
- JavaScript 基础(七) 箭头函数 generator Date JSON
- 初体验 Ghost : yet another WordPress?
- 浅谈MySQL的事务隔离级别
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ValueError: too many values to unpack (expected 2)
- VMware15更新后克隆Centos7发现网卡起不来了
- 基于SSH的医院在线挂号
- Linux-远程拷贝(scp命令)
- Kettle使用JavaScript代码处理数据
- Hadoop入门---(wordcount)统计单词出现的次数
- JS去除字符串的空格
- insertionSoft(插入排序) 2.1-1 And 重写insertionSoft 2.1-2
- Swagger-Springboot-mybatis-mysql
- Python+java+websocket+SpringMVC实时监控数据库中的表
- 基于Java图形界面的IPV4与网址的地址解析器
- 如何在千里之外能访问自己的电脑?(FRP)
- 三分钟Docker-镜像、容器实战篇
- 看懂今天这个!你就是个真正的javaer!
- 猿进化系列7——一文搞懂IO