我正在尝试构建一个类,它继承了Python列表中的方法,但也在上面做了一些额外的事情......在这一点上显示代码可能更容易......
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
我的问题是...如果我想在insert()
上执行与在append()
上执行的相同类型的对象接纳测试,我无法找到一种方法来编写新方法,而不牺牲对一个列表扩展方法的支持(即list.append()
、list.insert()
或list.extend()
)。如果我试图支持所有这些,我最终会得到递归循环。解决这个问题的最佳方法是什么?
编辑:我接受了关于子类化collections.MutableSequence而不是Python的list()的建议
结果代码...张贴在这里的情况下,它帮助别人...
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"""
# optional: self._acl_check(val)
del self._list[ii]
def __setitem__(self, ii, val):
# optional: self._acl_check(val)
self._list[ii] = val
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):
# optional: self._acl_check(val)
self._list.append(val)
4条答案
按热度按时间oo7oh9g91#
如果可以避免的话,不要从内置类继承(你可以,但这并不意味着你应该,除非有一个真正令人信服的理由)
这些类是为了速度而优化的,这使得正确地继承它们变得非常繁琐,因为最终必须重写几乎所有内容。
相反,从
collections.MutableSequence
继承可以让您实现一些基本方法,并获得序列API的健壮的全功能实现,而没有从list
继承所带来的所有怪癖和警告。vaqhlq812#
使用
isinstance
检查对象是否是Host
的示例,并使用super
(例如super(HostList, self).insert(...)
)使用list
的功能,而不是自己重新实现它。你应该以这样的方式结束:
1sbrub3j3#
除非有令人信服的理由让你的HostList容器完全支持可变容器接口,否则我建议使用has-a模型而不是is-a。你将有额外的负担来确保切片等操作的类型一致性(返回一个HostList容器而不是一个列表)。
vlju58qv4#
你可以用
super()
从你的方法调用list
的方法,这样你就不需要把它和其他方法混在一起了。