Python:从集合中检索项目

2023-11-23

一般来说,Python 集似乎并不是为通过键检索项目而设计的。显然这就是词典的用途。但是,无论如何,给定一个键,您可以从等于该键的集合中检索一个实例吗?

再说一次,我知道这正是字典的用途,但据我所知,有合理的理由想要用字典来做到这一点。假设您有一个类定义如下:

class Person:
   def __init__(self, firstname, lastname, age):
      self.firstname = firstname
      self.lastname = lastname
      self.age = age

现在,假设我要创建大量Person对象,每次我创建一个Person我需要确保它不是以前的对象的重复Person目的。 APerson被认为是另一个的重复Person如果他们有相同的firstname,不管其他实例变量。所以自然地,显而易见的事情就是插入所有Person对象到一个集合中,并定义一个__hash__ and __eq__方法使得Person对象通过它们的比较firstname.

另一种选择是创建一个字典Person对象,并使用单独创建的firstname字符串作为键。这里的缺点是我会重复firstname细绳。在大多数情况下这并不是真正的问题,但是如果我有 10,000,000 呢?Person物体?冗余字符串存储确实会开始增加内存使用量。

但如果两个Person对象比较相等,我需要能够检索原始对象,以便附加实例变量(除了firstname) 可以按照业务逻辑所需的方式进行合并。这让我回到了我的问题:我需要某种方法来从set.

有办法做到这一点吗?或者使用字典是这里唯一真正的选择吗?


我肯定会在这里使用字典。重复使用firstname实例变量作为字典键不会复制它——字典只会使用相同的对象。我怀疑字典会比集合使用更多的内存。

要真正节省内存,请添加__slots__归因于你的班级。这将防止 10,000,000 个实例中的每一个实例出现__dict__属性,这将比一个潜在的开销节省更多的内存dict over a set.

Edit:一些数字支持我的主张。我定义了一个愚蠢的示例类,存储随机字符串对:

def rand_str():
    return str.join("", (chr(random.randrange(97, 123))
                         for i in range(random.randrange(3, 16))))

class A(object):
    def __init__(self):
        self.x = rand_str()
        self.y = rand_str()
    def __hash__(self):
        return hash(self.x)
    def __eq__(self, other):
        return self.x == other.x

该类的一组 1,000,000 个实例使用的内存量

random.seed(42)
s = set(A() for i in xrange(1000000))

在我的机器上有 240 MB。如果我添加

    __slots__ = ("x", "y")

对于班级来说,这会减少到 112 MB。如果我将相同的数据存储在字典中

def key_value():
    a = A()
    return a.x, a

random.seed(42)
d = dict(key_value() for i in xrange(1000000))

这使用了 249 MB,没有__slots__和 121 MB__slots__.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python:从集合中检索项目 的相关文章

随机推荐