我需要一个 pythonlist
对象,它在插入时会自动检查表单的某些约束:“A 必须始终位于 B 之前”或“如果包含 C,则它必须始终位于最后”。
实现这一点的最简单/最快的方法是什么。显而易见的方法是覆盖列表数据类型的所有更改其内容的方法(append
、extend
、insert
等),并验证在操作后约束是否仍然有效。只是这很乏味,因为有很多这些方法。有没有更简单的方法?
我需要一个 pythonlist
对象,它在插入时会自动检查表单的某些约束:“A 必须始终位于 B 之前”或“如果包含 C,则它必须始终位于最后”。
实现这一点的最简单/最快的方法是什么。显而易见的方法是覆盖列表数据类型的所有更改其内容的方法(append
、extend
、insert
等),并验证在操作后约束是否仍然有效。只是这很乏味,因为有很多这些方法。有没有更简单的方法?
我强烈建议从collections.MutableSequence
抽象基类继承。缺点是它不会被识别为list
(正如user4815162342指出的那样)的子类。但是,只要使用结果类的人做正确的事情(即使用鸭子类型或将抽象基类而不是具体类传递给 isinstance
),这几乎无关紧要。
关于这一点的美妙之处在于,一旦您定义了以下方法,您就MutableSequence
可以免费获得界面的其余部分。这是一个具体的子类MutableSequence
,您可以将其用作进一步定制的模板。在您的情况下,您应该只需要自定义__init__
、__setitem__
、insert
和__delitem__
。其他所有内容都是根据这些定义的,因此将执行您插入的任何检查:
import collections
class MyList(collections.MutableSequence):
def __init__(self, it=()):
self._inner = list(it)
def __len__(self):
return len(self._inner)
def __iter__(self):
return iter(self._inner)
def __contains__(self, item):
return item in self._inner
def __getitem__(self, index):
return self._inner[index]
def __setitem__(self, index, value):
self._inner[index] = value
def __delitem__(self, index):
del self._inner[index]
def __repr__(self):
return 'MyList({})'.format(self._inner)
def insert(self, index, item):
return self._inner.insert(index, item)
几个简单的测试:
>>> ml = MyList('foo')
>>> ml
MyList(['f', 'o', 'o'])
>>> ml.append(5)
>>> ml
MyList(['f', 'o', 'o', 5])
>>> ml.reverse()
>>> ml
MyList([5, 'o', 'o', 'f'])
如果您的类型必须是 的子类型list
,则您的选择是有限的。您必须继承并重写 mutator 方法,不要忘记特殊方法,例如__setitem__
. 坏消息是没有办法强制使用这些方法。任何人,在任何时候,都可以调用:list.append(your_list, new_elem)
,并绕过你的append
。更糟糕的是,Python 的实现在某些地方正是这样做的。(这在字典和元组中更常见。)
如果您的类型不需要继承 from list
,请查看UserList
和 at collections.MutableSequence
。
不要子类化list
,代理它:覆盖__getattribute__
以将所有调用传递给代理列表,然后检查您的约束。