Monday 3 August 2009

Python List Utility Classes

I've been adapting some Java code to Python recently and wanted some tighter control over list elements than the default list type. I've extended list with two custom classes. The first, TypedList restricts list elements to a given type or types e.g.

>>> t=TypedList(float)
>>> t+=[9]
Traceback (most recent call last):
File "", line 1, in
File "", line 34, in __iadd__
TypeError: List items must be of type float
The existing array type gives similar capability but with this you can put in any type ...


class TypedList(list):
"""Extend list type to enabled only items of a given type. Supports
any type where the array type in the Standard Library is restricted to
only limited set of primitive types
"""

def __init__(self, elementType, *arg, **kw):
"""@type elementType: type/tuple
@param elementType: object type or types which the list is allowed to
contain. If more than one type, pass as a tuple
"""
self.__elementType = elementType
super(TypedList, self).__init__(*arg, **kw)

def _getElementType(self):
return self.__elementType

elementType = property(fget=_getElementType,
doc="The allowed type or types for list elements")

def extend(self, iter):
for i in iter:
if not isinstance(i, self.__elementType):
raise TypeError("List items must be of type %s" %
(self.__elementType,))

return super(TypedList, self).extend(iter)

def __iadd__(self, iter):
for i in iter:
if not isinstance(i, self.__elementType):
raise TypeError("List items must be of type %s" %
(self.__elementType,))

return super(TypedList, self).__iadd__(iter)

def append(self, item):
if not isinstance(item, self.__elementType):
raise TypeError("List items must be of type %s" %
(self.__elementType,))

return super(TypedList, self).append(item)

For the second class I wanted a way of avoiding the addition of duplicate elements to a list:


>>> u=UniqList()
>>> u.append('a')
>>> u
['a']
>>> u.append('a')
>>> u
['a']

It silently ignores the duplicate element. It would be straightforward to alter to raise an exception if this was the preferred behaviour. Here's the class:


class UniqList(list):
"""Extended version of list type to enable a list with unique items.
If an item is added that is already present then it is silently omitted
from the list
"""
def extend(self, iter):
return super(UniqList, self).extend([i for i in iter if i not in self])

def __iadd__(self, iter):
return super(UniqList, self).__iadd__([i for i in iter
if i not in self])

def append(self, item):
for i in self:
if i == item:
return None

return super(UniqList, self).append(item)

No comments: