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.