将list.insert()方法模拟为Python的list的子类

ewm0tg9j  于 2023-04-10  发布在  Python
关注(0)|答案(4)|浏览(107)

我正在尝试构建一个类,它继承了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)
oo7oh9g9

oo7oh9g91#

如果可以避免的话,不要从内置类继承(你可以,但这并不意味着你应该,除非有一个真正令人信服的理由)
这些类是为了速度而优化的,这使得正确地继承它们变得非常繁琐,因为最终必须重写几乎所有内容。
相反,从collections.MutableSequence继承可以让您实现一些基本方法,并获得序列API的健壮的全功能实现,而没有从list继承所带来的所有怪癖和警告。

vaqhlq81

vaqhlq812#

使用isinstance检查对象是否是Host的示例,并使用super(例如super(HostList, self).insert(...))使用list的功能,而不是自己重新实现它。
你应该以这样的方式结束:

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)
1sbrub3j

1sbrub3j3#

除非有令人信服的理由让你的HostList容器完全支持可变容器接口,否则我建议使用has-a模型而不是is-a。你将有额外的负担来确保切片等操作的类型一致性(返回一个HostList容器而不是一个列表)。

vlju58qv

vlju58qv4#

你可以用super()从你的方法调用list的方法,这样你就不需要把它和其他方法混在一起了。

相关问题