Get/Search 集合中元素的引用

Get/Search reference of element in set

对于自定义对象,我有自定义 __eq____hash__ 函数,它仅依赖于唯一的 "name"。然后将此 class 的对象放入一个集合中。

现在我想 search/find 集合中的一个元素:

class Resource:
    def __init__(self, name, rest)
        self.name = name
        # ....

    def __hash__(self):
        return hash(self.name)

    def __eq__(self, other):
        return self.name == other.name

s = {Resource("test", 10), Resource("test2", 20)}

我怎样才能用 "equality": test 搜索对象?作为最后的手段,我可​​以使用字典,但这会很丑陋,因为 "key" 会存储在两个地方,这可能会导致严重的错误。


澄清一下:我不是在寻找 "in" 我是在寻找一种方法来 return 参考。

套装基本上是容器,通常用于收集独特的物品。它们没有顺序,并且不能直接访问各个元素。因此,从集合中获取元素是不可能的。

一个可能的解决方案是使用集合交集操作,就像这样

{Resource("test", 30)} & s

结果又是set。因此,您可能希望将其转换为列表或元组,然后从中访问元素。例如,

common = {Resource("test", 30)} & s
if common:
    result = tuple(common)[0]

即使现在,result 也不必是 set 中已经存在的对象。从 set 的角度来看,Resource("test", 30)Resource("test", 10) 是一回事,因为根据比较逻辑它们都是相等的。所以它可以选择 return 其中一个。无法保证您将从 set.

中获得相应的对象

PS:对于这个用例,我建议使用字典,正如您在问题本身中提到的那样。

我同意@thefourtheye;对于您展示的 class 示例,dict 可能是更好的选择。如果您的用例确实需要 set,那么您可以创建一个特殊的 class,它是 dictset 之间的交叉:

import collections

class MySuperSpecialSet(dict, collections.MutableSet):
    def __init__(self, it=[]):
        for v in it:
            self.add(v)

    def add(self, v):
        super(MySuperSpecialSet, self).__setitem__(v, v)

    def discard(self, v):
        try:
            super(MySuperSpecialSet, self).__delitem__(v)
        except Exception:
            pass

    # make sure some `dict` methods are hard to call by accident
    __setitem__ = None
    keys = iterkeys = viewkeys = None
    items = iteritems = viewitems = None
    values = itervalues = viewvalues = None
    copy = None
    fromkeys = None
    popitem = None

    # some MutableSet methods that should override dict methods
    pop = collections.MutableSet.pop
    update = collections.MutableSet.__ior__


s = MySuperSpecialSet([Resource("test", 10), Resource("test2", 20)])

test2 = Resource("test2", 2)
test2_orig = s[test2]

test2.rest == test2_orig.rest  # False

为了提高效率,您需要手动实现 collections.MutableSet 中的一些方法,但是这个准系统 class 几乎可以完成内置 set 可以做的所有事情以及 dict 可以做的一些事情(比如 __getitem__,这是你所要求的行为所需要的)。

我还建议您使散列更独特一些,这样您就不会与字符串发生散列冲突。像这样的东西会起作用:

class Resource(object):
    def __init__(self, name, rest)
        self.name = name
        # ....

    def _key(self):
        return (type(self), self.name)

    def __hash__(self):
        return hash(self._key())

    def __eq__(self, other):
        try:
            return self._key() == other._key()
        except AttributeError:
            return False