Fluent Python笔记--Python中的序列

2018-02-03  本文已影响25人  MontyOak

首先来了解一个概念--协议。在Python构建功能完善的序列没有必要使用继承,只需要实现序列所需要的协议即可。
而所谓的协议是指非正式的接口集合。比如,spam类只要实现了__len____getitem__两个方法,不管是谁的子类,它都会表现得像序列一样。

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

虽然FrechDeck没有继承任何序列,但它本身已经是序列了,因为它的行为和序列一样,这就叫做鸭子类型。
下面实现一个支持切片操作的序列:

class Vector:
    # 省略了很多行
    # ...
    def __len__(self):
        return len(self._components)

    def __getitem__(self, index):
        cls = type(self) 
        if isinstance(index, slice): 
            return cls(self._components[index]) 
        elif isinstance(index, numbers.Integral): 
            return self._components[index] 
        else:
            msg = '{cls.__name__} indices must be integers'
            raise TypeError(msg.format(cls=cls)) 

>>> v7 = Vector(range(7))
>>> v7[-1] 
6.0
>>> v7[1:4] 
Vector([1.0, 2.0, 3.0])
>>> v7[-1:] 
Vector([6.0])
>>> v7[1,2] 
Traceback (most recent call last):
...
TypeError: Vector indices must be integers

接下来我们添加代码,使vector类支持哈希操作:

from array import array
import reprlib
import math
import functools 
import operator 

class Vector:
    typecode = 'd'
    # 排版需要,省略了很多行...

    def __eq__(self, other): 
        return tuple(self) == tuple(other)

    def __hash__(self):
        hashes = map(hash, self._components)
        return functools.reduce(operator.xor, hashes, 0) 

    def __eq__(self, other):
    return len(self) == len(other) and all(a == b for a, b in zip(self,other))
上一篇 下一篇

猜你喜欢

热点阅读