在 Python 中重写 set 方法
问题描述
我想创建一个自定义集合,它会自动将对象转换为不同的形式以存储在集合中(请参阅 使用 Python 字典作为非嵌套键) 作为背景.
I want to create a custom set that will automatically convert objects into a different form for storage in the set (see Using a Python Dictionary as a key non-nested) for background.
如果我覆盖 add
、remove
、__contains__
、__str__
、update
,__iter__
,这足以使其他操作正常运行,还是我需要覆盖其他任何内容?
If I override add
, remove
, __contains__
, __str__
, update
, __iter__
, will that be sufficient to make the other operations behave properly, or do I need to override anything else?
解决方案
使用 collections
的抽象类,正如@kaizer.se 建议的那样,是 2.6 中的合适解决方案(不知道为什么你想调用 super —— 你试图委派哪些功能不能通过包含而不是继承来最好地完成?!).
Working from collections
's abstract classes, as @kaizer.se suggests, is the appropriate solution in 2.6 (not sure why you want to call super -- what functionality are you trying to delegate that can't best done by containment rather than inheritance?!).
确实你没有得到 update
-- 通过提供抽象方法,你得到 __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__,__xor__ 和 isdisjoint
(来自 collections.Set
)加上 clear、pop、remove、__ior__、__iand__、__ixor__ 和 __isub__
(来自 collections.MutableSet
),这远远超过您从子类化 set
(您必须覆盖 every 感兴趣的方法).您只需要提供您想要的其他设置方法.
It's true that you don't get update
-- by providing the abstract methods, you do get __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__ __sub__, __xor__, and isdisjoint
(from collections.Set
) plus clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__
(from collections.MutableSet
), which is far more than you'd get from subclassing set
(where you'd have to override every method of interest). You'll just have to provide other set methods you desire.
请注意,像 collections.Set
这样的抽象基类与具体类完全不同,包括像 set
这样的内置函数和(在 2.6 中)旧的 sets.Set
,已弃用但仍然存在(在 Python 3 中已删除).ABC 旨在继承自(并且可以在您实现所有抽象方法后从您那里合成一些方法,这是您必须的),其次是注册"类,因此它们看起来好像从它们继承而来,即使它们没有(使 isinstance
更实用和有用).
Note that the abstract base classes like collections.Set
are a pretty different beast from concrete classes, including builtins such as set
and (in 2.6) good old sets.Set
, deprecated but still around (removed in Python 3). ABCs are meant to inherit from (and can then synthesize some methods from you once you implement all the abstract methods, as you must) and secondarily to "register" classes with so they look as if they inherited from them even when they don't (to make isinstance
more useable and useful).
这是 Python 3.1 和 2.6 的一个工作示例(没有充分的理由使用 3.0,因为 3.1 只比它有优势,没有劣势):
Here's a working example for Python 3.1 and 2.6 (no good reason to use 3.0, as 3.1 only has advantages over it, no disadvantage):
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
相关文章