Emulating the list.insert () method as a subclass of Python list

I'm trying to create a class that inherits methods from a Python list, but also does some extra things on top ... maybe it's easier to just show the 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 that ... if I want to run the same object access tests on insert() , as it was on append() , I cannot find a way to code new methods without sacrificing support for one list expansion method ( i.e. list.append() , list.insert() or list.extend() ). If I try to support them all, I end up in recursive loops. What is the best way to solve this problem?

EDIT: I accepted the proposal for subclass collections. MutableSequence instead of Python () list

The resulting code ... posting here in case this helps someone ...

 from collections 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): """Get a list item""" 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) 
+6
source share
4 answers

If you can avoid this, do not inherit from built-in classes. (You can, but this does not mean that you should without a really compelling reason)

These classes are optimized for speed, and this makes inheriting from them tedious enough, since you have to redefine almost everything.

Inheriting from collections.MutableSequence instead, you can only implement a few basic methods and get a reliable, fully functional implementation of the sequence API without all the quirks and caveats that inherit from list .

+7
source

Use isinstance to check your objects to see if they are Host instances, and use super (e.g., super(HostList, self).insert(...) ) to use the list functionality rather than overriding it yourself.

You should get something like:

 def append(self, obj): """append to the list...""" if not isinstance(obj, Host): raise RuntimeError, "Cannot append a '%s' object to a HostList" % obj.__class__.__name__ super(HostList, self).append(obj) 
+6
source

If there is no convincing reason for your HostList container to fully support the container's mutable interface, I suggest using the has-a rather than is-a model. You will have the additional burden of ensuring type consistency with operations such as slicing (return the HostList container, not the list).

+3
source

You can call the list method from your method with super() . This way you do not need to clone it in other ways.

0
source

Source: https://habr.com/ru/post/885449/


All Articles