I'm trying to build a class that inherits methods from Python's list, but also does some additional things on top... it's probably easier just to show code at this point...
class Host(object):
"""Emulate a virtual host attached to a physical interface"""
def __init__(self):
# Insert class properties here...
pass
class HostList(list):
"""A container for managing lists of hosts"""
def __init__(self):
self = []
def append(self, hostobj):
"""append to the list..."""
if hostobj.__class__.__name__ == 'Host':
self.insert(len(self), hostobj)
else:
_classname = hostobj.__class__.__name__
raise RuntimeError, "Cannot append a '%s' object to a HostList" % _classname
My problem is this... if I want to perform the same kind of object admission tests on insert()
as I did on append()
, I can't find a way to code the new methods without to sacrificing support for one list expansion method (i.e. list.append()
, list.insert()
, or list.extend()
). If I try to support them all, I wind up with recursive loops. What is the best way around this problem?
EDIT: I took the suggestion about subclassing collections.MutableSequence instead of Python's list()
The resulting code... posting here in case, it helps someone...
from collections.abc import MutableSequence
class HostList(MutableSequence):
"""A container for manipulating lists of hosts"""
def __init__(self, data):
super(HostList, self).__init__()
if (data is not None):
self._list = list(data)
else:
self._list = list()
def __repr__(self):
return "<{0} {1}>".format(self.__class__.__name__, self._list)
def __len__(self):
"""List length"""
return len(self._list)
def __getitem__(self, ii):
# Good MutableSequence() implementation example in the cpython git repo:
# https://github.com/python/cpython/blob/208a7e957b812ad3b3733791845447677a704f3e/Lib/collections/__init__.py#L1215
if isinstance(ii, slice):
return self.__class__(self._list[ii])
else:
return self._list[ii]
def __delitem__(self, ii):
"""Delete an item"""
del self._list[ii]
def __setitem__(self, ii, val):
# optional: self._acl_check(val)
return self._list[ii]
def __str__(self):
return str(self._list)
def insert(self, ii, val):
# optional: self._acl_check(val)
self._list.insert(ii, val)
def append(self, val):
self.insert(len(self._list), val)
You can use the insert() method to insert an item to a list at a specified index. Each item in a list has an index. The first item has an index of zero (0), the second has an index of one (1), and so on.
__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .
We can create a list of object in Python by appending class instances/object to list. By this, every index in the list can point to instance attributes and methods of the class and can access them.
If you can possibly avoid it, don't inherit from builtin classes. (You can, but that doesn't mean you should without a really compelling reason)
Those classes are optimised for speed, and that makes inheriting from them correctly quite tedious, since you end up having to override almost everything.
Inheriting from collections.MutableSequence
instead lets you implement just a few essential methods, and get a robust fully featured implementation of the sequence API, without all the quirks and caveats that come with inheriting from list
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With