Overriding set methods in Python
我想创建一个自定义集,它将自动将对象转换为另一种形式,以便在该集中存储(请参见使用Python字典作为非嵌套键)作为背景。
如果我覆盖add、remove、__contains__、__str__、update、__iter__,这是否足以使其他操作正常运行,还是需要覆盖其他操作?
- @凯斯巴什:请不要对你自己的问题发表评论。即使是"好建议",从长远来看,也是相当愚蠢的。其他人希望你的问题和选定的答案没有很多毛绒的东西。
正如@kaizer.se所建议的,使用collections的抽象类是2.6中的合适解决方案(不确定为什么要调用super——您试图委托哪些功能不能最好地通过包含而不是继承来完成?!!)
的确,你没有得到update--通过提供抽象的方法,你得到了__le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, and isdisjoint(来自collections.Set)加上clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__(来自collections.MutableSet),这比你从set子类得到的要多得多(你必须覆盖所有感兴趣的方法)。你只需要提供你想要的其他方法。
请注意,像collections.Set这样的抽象基类与具体类是非常不同的,包括诸如set和(在2.6中)很好的旧sets.Set这样的内置类,尽管已弃用,但仍然存在(在python 3中删除)。ABC是从继承(然后可以在实现所有抽象方法后合成一些方法,正如您必须的那样),其次是用"注册"类,这样即使它们不继承,它们看起来也像是从它们继承的(使isinstance更有用)。
下面是Python3.1和2.6的一个工作示例(没有充分的理由使用3.0,因为3.1只比它有优势,没有劣势):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import collections
class LowercasingSet(collections.MutableSet):
def __init__(self, initvalue=()):
self._theset = set()
for x in initvalue: self.add(x)
def add(self, item):
self._theset.add(item.lower())
def discard(self, item):
self._theset.discard(item.lower())
def __iter__(self):
return iter(self._theset)
def __len__(self):
return len(self._theset)
def __contains__(self, item):
try:
return item.lower() in self._theset
except AttributeError:
return False |
- 它可以用key(item)来代替item.lower()无处不在->KeySet("Aa", key=operator.methodcaller('lower'))来推广。
- 你为什么要从Set而不是MutableSet分类?除了我之外,还有谁认为"收藏品"模块是"真实"收藏品(deque)和ABC的混合体这一点非常令人困惑?
- 值得注意的是,Set与Set不同。
- @JF和Kaizer,我的愚蠢打字错误——我提到了文本中的set/mutableset差异,然后在代码中使用前者,Fixed Now,TX。是的,casebash,python区分大小写(同样,set.set与collections.set不同,在py 2.6中设置,因为它们位于不同的模块和命名空间中)。@凯泽,是的,也许我们应该把ABC放在一个不同的模块中(但是ABC.py被用于较低层次的ABC基础设施,没有其他模块的名称作为令人信服的共识出现)。
- @JF,好主意——仅仅是这样的参数化在排序、最小、最大等方面被证明是非常有用的。在默认字典中沿着不同的轴。
- 为了将来的参考,这里有一个"keyedset"配方建立在mutableset上。code.activestate.com/recipes/576932
- @Kaizer.se,尼斯,德克萨斯州的指针。
在Python 2.6中:
1 2 3 4
| import collections
print collections.MutableSet.__abstractmethods__
# prints:
# frozenset(['discard', 'add', '__iter__', '__len__', '__contains__']) |
子类collections.MutableSet并重写上面列表中的方法。
更新方法本身非常简单,因为实现了上面的最小值。
1 2 3
| def update(self, iterable):
for x in iterable:
self.add(x) |
- 当我这样做时,我没有得到更新方法
- 另外,我不能调用super(使用python 3.0)
- @casebash:请在问题中包含python 3.0信息,而不是对答案的评论。