Move UserList to collections.

This commit is contained in:
Raymond Hettinger 2008-02-12 20:03:09 +00:00
parent 4513ef8b7a
commit 53dbe39b46
14 changed files with 133 additions and 143 deletions

View file

@ -1,9 +1,9 @@
:mod:`collections` --- High-performance container datatypes
===========================================================
:mod:`collections` --- Container datatypes
==========================================
.. module:: collections
:synopsis: High-performance datatypes
:synopsis: Container datatypes
.. moduleauthor:: Raymond Hettinger <python@rcn.com>
.. sectionauthor:: Raymond Hettinger <python@rcn.com>
@ -663,3 +663,45 @@ In addition to supporting the methods and operations of mappings,
.. attribute:: UserDict.data
A real dictionary used to store the contents of the :class:`UserDict` class.
:class:`UserList` objects
-------------------------
This class acts as a wrapper around list objects. It is a useful base class
for your own list-like classes which can inherit from them and override
existing methods or add new ones. In this way, one can add new behaviors to
lists.
The need for this class has been partially supplanted by the ability to
subclass directly from :class:`list`; however, this class can be easier
to work with because the underlying list is accessible as an attribute.
.. class:: UserList([list])
Class that simulates a list. The instance's contents are kept in a regular
list, which is accessible via the :attr:`data` attribute of :class:`UserList`
instances. The instance's contents are initially set to a copy of *list*,
defaulting to the empty list ``[]``. *list* can be any iterable, for
example a real Python list or a :class:`UserList` object.
In addition to supporting the methods and operations of mutable sequences,
:class:`UserList` instances provide the following attribute:
.. attribute:: UserList.data
A real :class:`list` object used to store the contents of the
:class:`UserList` class.
**Subclassing requirements:** Subclasses of :class:`UserList` are expect to
offer a constructor which can be called with either no arguments or one
argument. List operations which return a new sequence attempt to create an
instance of the actual implementation class. To do so, it assumes that the
constructor can be called with a single parameter, which is a sequence object
used as a data source.
If a derived class does not wish to comply with this requirement, all of the
special methods supported by this class will need to be overridden; please
consult the sources for information about the methods which need to be provided
in that case.

View file

@ -21,7 +21,7 @@ The following modules are documented in this chapter:
math.rst
cmath.rst
decimal.rst
rational.rst
fractions.rst
random.rst
itertools.rst
functools.rst

View file

@ -1,55 +1,3 @@
:mod:`UserList` --- Class wrapper for list objects
==================================================
.. module:: UserList
:synopsis: Class wrapper for list objects.
.. note::
This module is available for backward compatibility only. If you are writing
code that does not need to work with versions of Python earlier than Python 2.2,
please consider subclassing directly from the built-in :class:`list` type.
This module defines a class that acts as a wrapper around list objects. It is a
useful base class for your own list-like classes, which can inherit from them
and override existing methods or add new ones. In this way one can add new
behaviors to lists.
The :mod:`UserList` module defines the :class:`UserList` class:
.. class:: UserList([list])
Class that simulates a list. The instance's contents are kept in a regular
list, which is accessible via the :attr:`data` attribute of
:class:`UserList`
instances. The instance's contents are initially set to a copy of *list*,
defaulting to the empty list ``[]``. *list* can be any iterable, for
example a real Python list or a :class:`UserList` object.
In addition to supporting the methods and operations of mutable sequences (see
section :ref:`typesseq`), :class:`UserList` instances provide the following
attribute:
.. attribute:: UserList.data
A real Python list object used to store the contents of the :class:`UserList`
class.
**Subclassing requirements:** Subclasses of :class:`UserList` are expect to
offer a constructor which can be called with either no arguments or one
argument. List operations which return a new sequence attempt to create an
instance of the actual implementation class. To do so, it assumes that the
constructor can be called with a single parameter, which is a sequence object
used as a data source.
If a derived class does not wish to comply with this requirement, all of the
special methods supported by this class will need to be overridden; please
consult the sources for information about the methods which need to be provided
in that case.
:mod:`UserString` --- Class wrapper for string objects
======================================================

View file

@ -1,73 +0,0 @@
"""A more or less complete user-defined wrapper around list objects."""
import collections
class UserList(collections.MutableSequence):
def __init__(self, initlist=None):
self.data = []
if initlist is not None:
# XXX should this accept an arbitrary sequence?
if type(initlist) == type(self.data):
self.data[:] = initlist
elif isinstance(initlist, UserList):
self.data[:] = initlist.data[:]
else:
self.data = list(initlist)
def __repr__(self): return repr(self.data)
def __lt__(self, other): return self.data < self.__cast(other)
def __le__(self, other): return self.data <= self.__cast(other)
def __eq__(self, other): return self.data == self.__cast(other)
def __ne__(self, other): return self.data != self.__cast(other)
def __gt__(self, other): return self.data > self.__cast(other)
def __ge__(self, other): return self.data >= self.__cast(other)
def __cast(self, other):
if isinstance(other, UserList): return other.data
else: return other
def __cmp__(self, other):
return cmp(self.data, self.__cast(other))
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item
def __delitem__(self, i): del self.data[i]
def __add__(self, other):
if isinstance(other, UserList):
return self.__class__(self.data + other.data)
elif isinstance(other, type(self.data)):
return self.__class__(self.data + other)
else:
return self.__class__(self.data + list(other))
def __radd__(self, other):
if isinstance(other, UserList):
return self.__class__(other.data + self.data)
elif isinstance(other, type(self.data)):
return self.__class__(other + self.data)
else:
return self.__class__(list(other) + self.data)
def __iadd__(self, other):
if isinstance(other, UserList):
self.data += other.data
elif isinstance(other, type(self.data)):
self.data += other
else:
self.data += list(other)
return self
def __mul__(self, n):
return self.__class__(self.data*n)
__rmul__ = __mul__
def __imul__(self, n):
self.data *= n
return self
def append(self, item): self.data.append(item)
def insert(self, i, item): self.data.insert(i, item)
def pop(self, i=-1): return self.data.pop(i)
def remove(self, item): self.data.remove(item)
def count(self, item): return self.data.count(item)
def index(self, item, *args): return self.data.index(item, *args)
def reverse(self): self.data.reverse()
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
def extend(self, other):
if isinstance(other, UserList):
self.data.extend(other.data)
else:
self.data.extend(other)

View file

@ -162,6 +162,80 @@ def fromkeys(cls, iterable, value=None):
################################################################################
### UserList
################################################################################
class UserList(MutableSequence):
"""A more or less complete user-defined wrapper around list objects."""
def __init__(self, initlist=None):
self.data = []
if initlist is not None:
# XXX should this accept an arbitrary sequence?
if type(initlist) == type(self.data):
self.data[:] = initlist
elif isinstance(initlist, UserList):
self.data[:] = initlist.data[:]
else:
self.data = list(initlist)
def __repr__(self): return repr(self.data)
def __lt__(self, other): return self.data < self.__cast(other)
def __le__(self, other): return self.data <= self.__cast(other)
def __eq__(self, other): return self.data == self.__cast(other)
def __ne__(self, other): return self.data != self.__cast(other)
def __gt__(self, other): return self.data > self.__cast(other)
def __ge__(self, other): return self.data >= self.__cast(other)
def __cast(self, other):
return other.data if isinstance(other, UserList) else other
def __cmp__(self, other):
return cmp(self.data, self.__cast(other))
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item
def __delitem__(self, i): del self.data[i]
def __add__(self, other):
if isinstance(other, UserList):
return self.__class__(self.data + other.data)
elif isinstance(other, type(self.data)):
return self.__class__(self.data + other)
return self.__class__(self.data + list(other))
def __radd__(self, other):
if isinstance(other, UserList):
return self.__class__(other.data + self.data)
elif isinstance(other, type(self.data)):
return self.__class__(other + self.data)
return self.__class__(list(other) + self.data)
def __iadd__(self, other):
if isinstance(other, UserList):
self.data += other.data
elif isinstance(other, type(self.data)):
self.data += other
else:
self.data += list(other)
return self
def __mul__(self, n):
return self.__class__(self.data*n)
__rmul__ = __mul__
def __imul__(self, n):
self.data *= n
return self
def append(self, item): self.data.append(item)
def insert(self, i, item): self.data.insert(i, item)
def pop(self, i=-1): return self.data.pop(i)
def remove(self, item): self.data.remove(item)
def count(self, item): return self.data.count(item)
def index(self, item, *args): return self.data.index(item, *args)
def reverse(self): self.data.reverse()
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
def extend(self, other):
if isinstance(other, UserList):
self.data.extend(other.data)
else:
self.data.extend(other)
################################################################################
### Simple tests
################################################################################

View file

@ -4,7 +4,7 @@
import unittest, string, sys, struct
from test import test_support
from UserList import UserList
from collections import UserList
class Sequence:
def __init__(self, seq='wxyz'): self.seq = seq

View file

@ -1,7 +1,7 @@
import unittest
from test import test_support
from bisect import bisect_right, bisect_left, insort_left, insort_right, insort, bisect
from UserList import UserList
from collections import UserList
class TestBisect(unittest.TestCase):

View file

@ -5,7 +5,7 @@
run_with_locale
from operator import neg
import sys, warnings, random, collections, io, rational, fractions
import sys, warnings, random, collections, io, fractions
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
FutureWarning, __name__)
warnings.filterwarnings("ignore", "integer argument expected",
@ -210,7 +210,7 @@ def test_cmp(self):
# verify that circular objects are not handled
a = []; a.append(a)
b = []; b.append(b)
from UserList import UserList
from collections import UserList
c = UserList(); c.append(c)
self.assertRaises(RuntimeError, cmp, a, b)
self.assertRaises(RuntimeError, cmp, b, c)

View file

@ -1,6 +1,5 @@
from test.test_support import verify, verbose, TestFailed, sortdict
from UserList import UserList
from collections import UserDict
from collections import UserDict, UserList
def e(a, b):
print(a, b)

View file

@ -5,7 +5,7 @@
from weakref import proxy
from test.test_support import TESTFN, findfile, run_unittest
from UserList import UserList
from collections import UserList
class AutoFileTests(unittest.TestCase):
# file tests for which a test file is automatically set up

View file

@ -7,7 +7,7 @@
from weakref import proxy
from test.test_support import TESTFN, findfile, run_unittest
from UserList import UserList
from collections import UserList
import _fileio

View file

@ -254,7 +254,7 @@ def do(bad):
def test_recursion(self):
# Check that comparison for recursive objects fails gracefully
from UserList import UserList
from collections import UserList
a = UserList()
b = UserList()
a.append(b)

View file

@ -1,6 +1,6 @@
# Check every path through every method of UserList
from UserList import UserList
from collections import UserList
import unittest
from test import test_support, list_tests

View file

@ -1,7 +1,7 @@
import gc
import sys
import unittest
import UserList
import collections
import weakref
from test import test_support
@ -157,7 +157,7 @@ def test_basic_proxy(self):
o = C()
self.check_proxy(o, weakref.proxy(o))
L = UserList.UserList()
L = collections.UserList()
p = weakref.proxy(L)
self.failIf(p, "proxy for empty UserList should be false")
p.append(12)
@ -171,11 +171,11 @@ def test_basic_proxy(self):
p[1] = 5
self.assertEqual(L[1], 5)
self.assertEqual(p[1], 5)
L2 = UserList.UserList(L)
L2 = collections.UserList(L)
p2 = weakref.proxy(L2)
self.assertEqual(p, p2)
## self.assertEqual(repr(L2), repr(p2))
L3 = UserList.UserList(range(10))
L3 = collections.UserList(range(10))
p3 = weakref.proxy(L3)
self.assertEqual(L3[:], p3[:])
self.assertEqual(L3[5:], p3[5:])