怎样让len()等python原生函数适用于自定义的数据类型

想要让len()等python原生函数适用于自定义的数据类型,就需要在类中实现python的特殊方法。特殊方法是双下划线开头和结尾的方法。看下面的例子:

#一摞python风格的扑克牌
import collections

Card=collections.namedtuple('Card', ['rank','suit'])
class FrenchDeck:
    ranks=[str(n) for n in range(2,11)]+list('JQKA')
    suits='spades diamends clubs hearts'.split()
    def __init__(self):
        self._cards=[Card(rank,suit) for rank in self.ranks
                                     for suit in self.suits]
    def __len__(self):
        return len(self._cards)
    def __getitem__(self,position):
        return self._card[position]

In [33]: deck=FrenchDeck()

In [34]: len(deck)
Out[34]: 52

从一摞纸牌中抽取一张特定的牌:deck[0]。这是由__getitem__方法提供的:

In [38]: deck[0]
Out[38]: Card(rank='2', suit='spades')

我们需要单独写一个方法随机抽一张牌吗?不需要,python中已经内置了从一个序列中随机选取一个元素的方法random.choice,我们直接把它用在这一摞纸牌实例上就好:

In [39]: from random import choice

In [40]: choice(deck)
Out[40]: Card(rank='3', suit='spades')

好的,现在我们已经可以体会到在类中实现特殊方法的好处了:

  1. 使用类的时候不用再记忆自定义的方法名,取而代之的是python通用函数。
  2. 可以方便的使用python标准库,比如random.choice,从而不用重复发明轮子。

好戏还在后面。
因为__getItem__方法把[]操作交给了self._cards列表,所以我们的deck会自动支持列表的操作,比如切片,迭代,反向迭代。

In [41]: deck[12::13]
Out[41]: 
[Card(rank='5', suit='spades'),
 Card(rank='8', suit='diamends'),
 Card(rank='J', suit='clubs'),
 Card(rank='A', suit='hearts')]

In [43]: for card in reversed(deck):
    ...:     print(card)
    ...:     
Card(rank='A', suit='hearts')
Card(rank='A', suit='clubs')
Card(rank='A', suit='diamends')
Card(rank='A', suit='spades')
Card(rank='K', suit='hearts')
...

参考:流畅的python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值