gpt4 book ai didi

python - 设置对象有比较键吗?

转载 作者:行者123 更新时间:2023-12-01 04:01:51 25 4
gpt4 key购买 nike

是否有一种方法可以为 set() 提供比较器,以便在添加项目时检查该项目的属性是否相似,而不是该项目是否相同?例如,我想使用一组对象,其中一个属性可以包含相同的值。

class TestObj(object):
def __init__(self, value, *args, **kwargs):
self.value = value
super().__init__(*args, **kwargs)

values = set()
a = TestObj('a')
b = TestObj('b')
a2 = TestObj('a')
values.add(a) # Ok
values.add(b) # Ok
values.add(a2) # Not ok but still gets added

# Hypothetical code
values = set(lambda x, y: x.value != y.value)
values.add(a) # Ok
values.add(b) # Ok
values.add(a2) # Not added

我已经实现了自己的某种东西,它具有类似的功能,但想知道是否有内置的方法。

from Queue import Queue
class UniqueByAttrQueue(Queue):
def __init__(self, attr, *args, **kwargs):
Queue.__init__(self, *args, **kwargs)
self.attr = attr

def _init(self, maxsize):
self.queue = set()

def _put(self, item):
# Potential race condition, worst case message gets put in twice
if hasattr(item, self.attr) and item not in self:
self.queue.add(item)

def __contains__(self, item):
item_attr = getattr(item, self.attr)
for x in self.queue:
x_attr = getattr(x, self.attr)
if x_attr == item_attr:
return True
return False

def _get(self):
return self.queue.pop()

最佳答案

只需定义 __hash____eq__就相关属性而言,它可以与 set 一起使用。例如:

class TestObj(object):
def __init__(self, value, *args, **kwargs):
self.value = value
super().__init__(*args, **kwargs)

def __eq__(self, other):
if not instance(other, TestObj):
return NotImplemented
return self.value == other.value

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

如果您无法更改对象(或者不想更改,例如,因为其他事情对于平等很重要),则使用 dict 代替。您可以执行以下任一操作:

mydict[obj.value] = obj

所以新对象取代旧对象,或者

mydict.setdefault(obj.value, obj)

如果有问题的已经在键中,那么旧的对象就会被保留。只需确保使用 .viewvalues() (Python 2) 或 .values() (Python 3) 进行迭代,而不是直接迭代(这将获取键,而不是值)。您实际上可以使用这种方法来创建一个自定义的类似 set 的对象,其中包含您所描述的键(尽管您需要实现比我展示的更多的方法才能使其高效,但默认方法是通常相当慢):

from collections.abc import MutableSet  # On Py2, collections without .abc

class keyedset(MutableSet):
def __init__(self, it=(), key=lambda x: x):
self.key = key
self.contents = {}
for x in it:
self.add(x)

def __contains__(self, x):
# Use anonymous object() as default so all arguments handled properly
sentinel = object()
getval = self.contents.get(self.key(x), sentinel)
return getval is not sentinel and getval == x

def __iter__(self):
return iter(self.contents.values()) # itervalues or viewvalues on Py2

def __len__(self):
return len(self.contents)

def add(self, x):
self.contents.setdefault(self.key(x), x)

def discard(self, x):
self.contents.pop(self.key(x), None)

关于python - 设置对象有比较键吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36345425/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com