【问题标题】:Overriding set methods in Python在 Python 中重写 set 方法
【发布时间】:2009-10-26 01:30:02
【问题描述】:

我想创建一个自定义集合,它会自动将对象转换为不同的形式以存储在集合中(请参阅Using a Python Dictionary as a key non-nested)作为背景。

如果我覆盖addremove__contains____str__update__iter__,是否足以使其他操作正常运行,或者我是否需要覆盖其他任何操作?

【问题讨论】:

  • @Casebash:请不要评论您自己的问题。从长远来看,即使是“好建议”也很愚蠢。其他人想要你的问题和选择的答案,而不需要太多花里胡哨的东西。

标签: python python-3.x set


【解决方案1】:

正如@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 更加实用和有用)。

这是 Python 3.1 和 2.6 的一个工作示例(没有充分的理由使用 3.0,因为 3.1 只比它有优势,没有劣势):

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 的混合是非常令人困惑的?
  • 值得注意的是Setset不一样
  • @JF 和 kaizer,我的愚蠢错字——我在文本中提到了 Set / MutableSet 的区别,然后在代码中使用了前者,现在已修复,tx。是的,Casebash,Python 区分大小写(sets.Set 与 Py 2.6 中的 collections.Set 不同,因为它们位于不同的模块和命名空间中)。 @kaizer,是的,也许我们应该将 ABC 放在不同的模块中(但是 abc.py 被用于较低级别的 ABC 基础设施,没有其他模块名称作为令人信服的共识出现)。
  • 为了将来参考,这里有一个基于 MutableSet 的“KeyedSet”配方。 code.activestate.com/recipes/576932
【解决方案2】:

在 Python 2.6 中:

import collections
print collections.MutableSet.__abstractmethods__
# prints:
# frozenset(['discard', 'add', '__iter__', '__len__', '__contains__'])

子类 collections.MutableSet 并覆盖上面列表中的方法。

更新方法本身非常简单,只要实现了上面的最低限度

def update(self, iterable):
    for x in iterable:
        self.add(x)

【讨论】:

  • 另外我不能调用 super(使用 Python 3.0)
  • @Casebash:请在问题中包含 Python 3.0 信息,而不是对答案的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 2013-12-26
  • 1970-01-01
相关资源
最近更新 更多