Cha*_*l72 6 python set python-3.x
通常,Python集似乎不是为按键检索项而设计的.这显然是字典的用途.但是,无论如何,给定一个键,你可以从一个等于键的集合中检索一个实例?
同样,我知道这正是字典的用途,但据我所知,有一些合理的理由想要用字符集来完成.假设您有一个类定义类似于:
class Person:
def __init__(self, firstname, lastname, age):
self.firstname = firstname
self.lastname = lastname
self.age = age
Run Code Online (Sandbox Code Playgroud)
现在,假设我要创建大量Person对象,每次创建Person对象时,我都需要确保它不是前一个Person对象的副本.如果它们具有相同的A,Person则被认为是另一个的副本,而不管其他实例变量.因此,显而易见的事情是将所有对象插入到集合中,并定义一个和方法,以便通过它们来比较对象.PersonfirstnamePerson__hash____eq__Personfirstname
另一种选择是创建Person对象字典,并使用单独创建的firstname字符串作为键.这里的缺点是我要复制firstname字符串.在大多数情况下,这不是一个真正的问题,但如果我有10,000,000个Person对象怎么办?冗余字符串存储可能真的开始在内存使用方面加起来.
但是如果两个Person对象的比较相同,我需要能够检索原始对象,以便firstname可以按照业务逻辑所需的方式合并其他实例变量(除了).这让我回到了我的问题:我需要一些方法来从a中检索实例set.
反正有没有这样做?或者使用字典是唯一真正的选择?
我肯定会在这里使用字典.将firstname实例变量重用为字典键不会复制它 - 字典将只使用相同的对象.我怀疑字典会比集合使用更多的内存.
要实际节省内存,__slots__请在类中添加属性.这将阻止每个10,000,000个实例拥有一个__dict__属性,这将比一个dict超过a 的潜在开销节省更多的内存set.
编辑:一些数字支持我的说法.我定义了一个存储随机字符串对的愚蠢示例类:
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
Run Code Online (Sandbox Code Playgroud)
此类的一组1,000,000个实例使用的内存量
random.seed(42)
s = set(A() for i in xrange(1000000))
Run Code Online (Sandbox Code Playgroud)
在我的机器240 MB.如果我加
__slots__ = ("x", "y")
Run Code Online (Sandbox Code Playgroud)
在课堂上,这个数字下降到112 MB.如果我将相同的数据存储在字典中
def key_value():
a = A()
return a.x, a
random.seed(42)
d = dict(key_value() for i in xrange(1000000))
Run Code Online (Sandbox Code Playgroud)
这使用249 MB没有__slots__和121 MB __slots__.
| 归档时间: |
|
| 查看次数: |
760 次 |
| 最近记录: |