Container Special Methods
When designing a class that behaves like a container, it helps to
provide definitions for the essential operators that are common to
sequences, sets and mappings. Depending on whether your collection is
more like a set (with no index), a list (indexed by simple integers) or
a mapping (indexed by other objects), there are a number of additional
methods you should provide.
Additionally, the container classes have numerous method names
which aren't special. For example, sequence types also provide method
with ordinary names like append
,
count
, index
,
insert
, pop
,
remove
, reverse
and
sort
. To provide a complete implemetation, you'll
use special method names and ordinary method names.
Generally, we don't create our own containers from scratch. Most
often we subclass an existing container, adding our new methods to the
containers methods. We would use something like class MyList( list
):
to extend the built-in list class. We looked at this approach
in the section called “Sample
Class with Statistical
Methods”.
One might want to create a new container class that has a
sophisticated binary-tree implementation. This class behaves generally
like a sequence, except that data is stored in order, and searches can
be done much more rapidly than a simple sequence. It could be thought of
as an implementation that extends the built-in sequence type.
By providing the following special methods, your class behaves
like the built-in sequence, set or dictionary classes.
method function |
original expression |
__len__ (
self
) →
integer |
len . Note that if an object lacks a
__nonzero__ method and the
__len__ method returns zero, the object is
considered to be False in a Boolean
context. |
__getitem__ (
self
,
key
) → object |
self
[
key
]
. For sequence types,
the accepted keys should be integers or
slice objects. The special interpretation
of negative indexes (if the class wishes to emulate a sequence
type) must be supported by the __getitem__
method. If
key
is of an inappropriate
type, TypeError may be raised; if
of a value outside the set of indexes for the sequence (after any
special interpretation of negative values),
IndexError should be raised. The
for
statement requires an
IndexError will be raised for
illegal indexes to allow proper detection of the end of the
sequence. |
__setitem__ (
self
,
key
,
value
) |
self
[
key
] =
expression
. See
getitem . This should only be implemented for
mappings if the objects support changes to the values for keys, or
if new keys can be added, or for sequences if elements can be
replaced. The same exceptions should be raised for improper
key
values as for the
getitem method. |
__delitem__ (
self
,
key
) |
self
[
key
]
. See
getitem . This should only be implemented for
mappings if the objects support removal of keys, or for sequences
if elements can be removed from the sequence. The same exceptions
should be raised for improper
key
values as for the getitem method. |
__contains__ (
self
,
item
) |
item
in
self
operator. Return
True if
item
is in
self
. |
__missing__ (
self
,
key
) |
This is invoked by __getitem__ if the
key
does not exist. It can return an
appropriate default value. |
The __getitem__
,
__setitem__
,
__delitem__
method functions should be prepared
for the
key
to be either a
simple integer, a slice
object, or a tuple of
slice
objects. A slice
is
a simple object with three attributes:
start
,
stop
and
step
. The
following examples show common slice situations.
-
The expression someSequence[1:5]
is transformed
to someSequence.__getitem__( slice(1,5) )
. The
slice
object is assigned to the
key
parameter of the
__getitem__
function. This
slice
object has the following attribute
values: key.start
= 1,
key.stop
= 5, key.step
=
None
.
-
The expression someSequence[2:8:2]
is transformed
to someSequence.__getitem__( slice(2,8,2) )
. The
slice
object is assigned to the
key
parameter has the following attribute
values: key.start
= 2,
key.stop
= 8, key.step
=
2.
-
The expression someSequence[1:3,5:8]
is
transformed into someSequence.__getitem__( ( slice(1,3),
slice(5,8) ) )
. With a tuple of slice objects.
Sequence types should also provide the methods
append
, count
,
index
, insert
,
pop
, remove
,
reverse
and sort
, with the
same basic meanings as those for the built-in Python lists.
Additionally, sequence types should also implement concatenation
(via the + operator) and repetition (via the * operator) by defining
__add__
, __radd__
,
__iadd__
, __mul__
,
__rmul__
, and __imul__
. These
were described in the section called “Numeric Type Special Methods” in a numeric
context. The same methods, used in a container context, implement
different behaviors.
Mappings should also provide the methods
keys
, values
,
items
, has_key
,
get
, clear
,
copy
, and update
with the same
meanings as those for built-in Python mappings.