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,它是 dict
和 set
之间的交叉:
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
对于自定义对象,我有自定义 __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,它是 dict
和 set
之间的交叉:
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