Python:从集合中检索项目

标签 python python-3.x set

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

再一次,我知道这正是字典的用途,但据我所知,有正当理由想要对集合执行此操作。假设您有一个定义如下的类:

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

现在,假设我要创建大量的 Person 对象,每次我创建一个 Person 对象时,我都需要确保它不是先前 Person 对象的副本。一个 Person 被认为是另一个 Person 的副本,如果他们有相同的 firstname,而不考虑其他实例变量。所以很自然地,要做的事情就是将所有 Person 对象插入到一个集合中,并定义一个 __hash____eq__ 方法,以便 Person 对象按它们的 firstname 进行比较。

另一种选择是创建 Person 对象的字典,并使用单独创建的 firstname 字符串作为键。这里的缺点是我会复制 firstname 字符串。在大多数情况下这并不是真正的问题,但是如果我有 10,000,000 个 Person 对象怎么办?就内存使用而言,冗余字符串存储可能真的开始增加。

但是如果两个 Person 对象比较相等,我需要能够检索原始对象,以便可以将其他实例变量(firstname 除外)合并到业务逻辑所需的一种方式。这让我回到了我的问题:我需要一些方法来从 set 中检索实例。

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

最佳答案

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

要真正节省内存,请将 __slots__ 属性添加到您的类中。这将防止 10,000,000 个实例中的每一个都具有 __dict__ 属性,这将比 dictset 的潜在开销节省更多的内存>.

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

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")

对于类(class)来说,这下降到 112 MB。如果我将相同的数据存储在字典中

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

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

这在没有 __slots__ 的情况下使用 249 MB,在有 __slots__ 的情况下使用 121 MB。

关于Python:从集合中检索项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5979861/

相关文章:

Python 如何通过使用 oauthlib 的帐户身份验证获取 ID_Token 以与 Open ID Connect 一起使用

java - 如何将具有唯一字段的对象添加到 Set

javascript - javascript中的Grails <g:set标记

python - 使用 python 使用 for 循环导入文本文件

python-3.x - 如何在列表的解析参数中解析列表(字符串)而不是列表(字符)?

python-3.x - 来自 python worker :. 的错误 .. SyntaxError: invalid syntax

object - 无边框线的 Gnuplot png 文件

python - 从日期中减去 timedelta - pandas

python - 启动 [Selenium] [Python] 后 Chrome 崩溃

python - 我可以使用 BeautifulSoup 删除脚本标签吗?