3.3.7. 模拟容器类型
可以定义下列方法来实现容器对象。 容器通常属于序列(如列表或元组)或映射(如字典),但也存在其他形式的容器。 前几个方法集被用于模拟序列或是模拟映射;两者的不同之处在于序列允许的键应为整数 k 且 0 <= k < N
其中 N 是序列或定义指定区间的项的切片对象的长度。 此外还建议让映射提供 keys()
, values()
, items()
, get()
, clear()
, setdefault()
, pop()
, popitem()
, copy()
以及 update()
等方法,它们的行为应与 Python 标准字典对象的相应方法类似。 此外 collections.abc
模块提供了一个 MutableMapping
抽象基类以便根据由 getitem()
, setitem()
, delitem()
, 和 keys()
组成的基本集来创建所需的方法。 可变序列还应像 Python 标准列表对象那样提供 append()
, count()
, index()
, extend()
, insert()
, pop()
, remove()
, reverse()
和 sort()
等方法。 最后,序列类型还应通过定义下文描述的 add()
, radd()
, iadd()
, mul()
, rmul()
和 imul()
等方法来实现加法(指拼接)和乘法(指重复);它们不应定义其他数值运算符。 此外还建议映射和序列都实现 contains()
方法以允许高效地使用 in
运算符;对于映射,in
应该搜索映射的键;对于序列,则应搜索其中的值。 另外还建议映射和序列都实现 iter()
方法以允许高效地迭代容器中的条目;对于映射,iter()
应当迭代对象的键;对于序列,则应当迭代其中的值。
object.
len
(self)- 调用此方法以实现内置函数
len()
。应该返回对象的长度,以一个>=
0 的整数表示。此外,如果一个对象未定义bool()
方法而其len()
方法返回值为零,则在布尔运算中会被视为假值。
CPython implementation detail: 在 CPython 中,要求长度最大为 sys.maxsize
。如果长度大于 sys.maxsize
则某些特性 (例如 len()
) 可能会引发 OverflowError
。要通过真值检测来防止引发 OverflowError
,对象必须定义 bool()
方法。
object.
length_hint
(self)- 调用此方法以实现
operator.length_hint()
。 应该返回对象长度的估计值(可能大于或小于实际长度)。 此长度应为一个>=
0 的整数。 返回值也可以为NotImplemented
,这会被视作与length_hint
方法完全不存在时一样处理。 此方法纯粹是为了优化性能,并不要求正确无误。
3.4 新版功能.
注解
切片是通过下述三个专门方法完成的。以下形式的调用
- a[1:2] = b
会为转写为
- a[slice(1, 2, None)] = b
其他形式以此类推。略去的切片项总是以 None
补全。
object.
getitem
(self, key)- 调用此方法以实现
self[key]
的求值。对于序列类型,接受的键应为整数和切片对象。请注意负数索引(如果类想要模拟序列类型)的特殊解读是取决于getitem()
方法。如果 key 的类型不正确则会引发TypeError
异常;如果为序列索引集范围以外的值(在进行任何负数索引的特殊解读之后)则应引发IndexError
异常。对于映射类型,如果 key 找不到(不在容器中)则应引发KeyError
异常。
注解
for
循环在有不合法索引时会期待捕获 IndexError
以便正确地检测到序列的结束。
object.
setitem
(self, key, value)- 调用此方法以实现向
self[key]
赋值。注意事项与getitem()
相同。为对象实现此方法应该仅限于需要映射允许基于键修改值或添加键,或是序列允许元素被替换时。不正确的 key 值所引发的异常应与getitem()
方法的情况相同。
object.
delitem
(self, key)- 调用此方法以实现
self[key]
的删除。注意事项与getitem()
相同。为对象实现此方法应该权限于需要映射允许移除键,或是序列允许移除元素时。不正确的 key 值所引发的异常应与getitem()
方法的情况相同。
迭代器对象也需要实现此方法;它们需要返回对象自身。有关迭代器对象的详情请参看 迭代器类型 一节。
object.
reversed
(self)- 此方法(如果存在)会被
reversed()
内置函数调用以实现逆向迭代。它应当返回一个新的以逆序逐个迭代容器内所有对象的迭代器对象。
如果未提供 reversed()
方法,则 reversed()
内置函数将回退到使用序列协议 (len()
和 getitem()
)。支持序列协议的对象应当仅在能够提供比 reversed()
所提供的实现更高效的实现时才提供 reversed()
方法。
成员检测运算符 (in
和 not in
) 通常以对容器进行逐个迭代的方式来实现。 不过,容器对象可以提供以下特殊方法并采用更有效率的实现,这样也不要求对象必须为可迭代对象。
object.
contains
(self, item)- 调用此方法以实现成员检测运算符。如果 item 是 self 的成员则应返回真,否则返回假。对于映射类型,此检测应基于映射的键而不是值或者键值对。
对于未定义 contains()
的对象,成员检测将首先尝试通过 iter()
进行迭代,然后再使用 getitem()
的旧式序列迭代协议,参看 语言参考中的相应部分。