假设您有这个课程:
class Thingy(object): def __init__(self, key, notkey): self.key, self.notkey = key, notkey def __eq__(self, other): return self.key == other.key def __hash__(self): return hash(self.key)
现在,您想将它们放在集合中,但是用
notkey代替
key。您不能按原样进行操作,因为set期望其元素具有相同的相等性含义-
以及对hash的一致含义(
a == b总是意味着)
hash(a) == hash(b)。因此,创建一个包装器:
class WrappedThingy(object): def __init__(self, thingy): self.thingy = thingy def __eq__(self, other): return self.thingy.notkey == other.thingy.notkey def __hash__(self): return hash(self.thingy.notkey)
您可以将 它们 放在集合中:
wts = set(WrappedThingy(thingy) for thingy in thingies)
例如,假设您要对自己的东西进行唯一化,为每个
notkey值精确地(任意)保持一个东西。只需包装它们,将包装器粘在一个集合中,然后解开包装,然后将展开的对象粘在列表中:
wts = set(WrappedThingy(thingy) for thingy in thingies)thingies = [wt.thingy for wt in wts]
这是更通用的Python模式“ DSU”的一部分。这代表“ decorate-sort-
undecorate”,这在当今已经非常不准确了,因为在现代Python中几乎不需要它来执行与排序相关的任务……但是从历史上看,它是有道理的。随意称其为“装饰过程无法装饰”,希望它能流行起来,但不要太过努力。
您现在不需要DSU进行排序的原因是,大多数排序函数都将
key函数作为参数。实际上,即使是唯一化,配方中的
unique_everseen功能也需要一个。
itertools
key
但是,如果您仔细看一下它的功能,基本上就是DSU:
for element in iterable: k = key(element) if k not in seen: seen.add(k) yield element
(事实上,它是一个生成器,而不是一个列表构建函数,这意味着它可以“即时取消装饰”,这使事情变得简单一些。但是除此之外,相同的想法。)



