Python基础教程​基本的序列和映射协议

9.3.1 基本的序列和映射协议

序列和映射基本上是元素(item)的集合,要实现它们的基本行为(协议),不可变对象需要实现2个方法,而可变对象需要实现4个。

 __len__(self):这个方法应返回集合包含的项数,对序列来说为元素个数,对映射来说为键值对数。如果__len__返回零(且没有实现覆盖这种行为的__nonzero__),对象在布尔上下文中将被视为假(就像空的列表、元组、字符串和字典一样)。

 __getitem__(self, key):这个方法应返回与指定键相关联的值。对序列来说,键应该是0~n 1的整数(也可以是负数,这将在后面说明),其中n为序列的长度。对映射来说,键可以是任何类型。

 __setitem__(self, key, value):这个方法应以与键相关联的方式存储值,以便以后能够使用__getitem__来获取。当然,仅当对象可变时才需要实现这个方法。

 __delitem__(self, key):这个方法在对对象的组成部分使用__del__语句时被调用,应删除与key相关联的值。同样,仅当对象可变(且允许其项被删除)时,才需要实现这个方法。

对于这些方法,还有一些额外的要求。

 对于序列,如果键为负整数,应从末尾往前数。换而言之, x[-n]应与x[len(x)-n]等效。

 如果键的类型不合适(如对序列使用字符串键),可能引发TypeError异常。

 对于序列,如果索引的类型是正确的,但不在允许的范围内,应引发IndexError异常。

要了解更复杂的接口和使用的抽象基类(Sequence),请参阅有关模块collections的文档。

下面来试一试,看看能否创建一个无穷序列。

def check_index(key):

"""

指定的键是否是可接受的索引?

键必须是非负整数,才是可接受的。如果不是整数,

将引发TypeError异常;如果是负数,将引发Index

Error异常(因为这个序列的长度是无穷的)

"""

if not isinstance(key, int):

raiseTypeError

if key

raise IndexError

class ArithmeticSequence:

def __init__(self, start=0, step=1):

"""

初始化这个算术序列

start -序列中的第一个值

step -两个相邻值的差

changed -一个字典,包含用户修改后的值

"""

self.start = start # 存储起始值

self.step = step # 存储步长值

self.changed = {} # 没有任何元素被修改

def __getitem__(self, key):

"""

从算术序列中获取一个元素

"""

check_index(key)

try:

return self.changed[key] # 修改过?

except KeyError: # 如果没有修改过,

return self.start + key * self.step # 就计算元素的值

def __setitem__(self, key, value):

"""

修改算术序列中的元素

"""

check_index(key)

self.changed[key] = value # 存储修改后的值

这些代码实现的是一个算术序列,其中任何两个相邻数字的差都相同。第一个值是由构造函数的参数start(默认为0)指定的,而相邻值之间的差是由参数step(默认为1)指定的。你允许用户修改某些元素,这是通过将不符合规则的值保存在字典changed中实现的。如果元素未被修改,就使用公式self.start + key * self.step来计算它的值。

下面的示例演示了如何使用这个类:

>>> s = ArithmeticSequence(1, 2)

9

>>> s[4] = 2

2

11

请注意,我要禁止删除元素,因此没有实现__del__:

>>> del s[4]

Traceback (most recent call last):

File "", line 1, in?

AttributeError: ArithmeticSequence instancehas no attribute '__delitem__'

另外,这个类没有方法__len__,因为其长度是无穷的。

如果所使用索引的类型非法,将引发TypeError异常;如果索引的类型正确,但不在允许的范围内(即为负数),将引发IndexError异常。

>>> s["four"]

Traceback (most recent call last):

File "", line 1, in?

File "arithseq.py", line 31, in__getitem__

check_index(key)

File "arithseq.py", line 10, incheckIndex

ifnot isinstance(key, int): raiseTypeError

TypeError

>>> s[-42]

Traceback (most recent call last):

File "", line 1, in?

File "arithseq.py", line 31, in__getitem__

check_index(key)

File "arithseq.py", line 11, incheckIndex

if key

IndexError

索引检查是由我为此编写的辅助函数check_index负责的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181206G0841700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券