手动实现python字符串插入
我试图减少Python程序的内存占用,发现有大量字符串具有相同的值,但不同的手动实现python字符串插入,python,Python,我试图减少Python程序的内存占用,发现有大量字符串具有相同的值,但不同的id。我可以intern字符串,但知道interning是如何工作的,在我看来,将这些字符串引入全局字典是一件很麻烦的事情,每当在我的程序中到处创建新字符串时,都会使用全局字典 所以我写了这个: def _coalesce_str(s, candidates): for candidate in candidates: if s == candidate: return c
id
。我可以intern
字符串,但知道interning是如何工作的,在我看来,将这些字符串引入全局字典是一件很麻烦的事情,每当在我的程序中到处创建新字符串时,都会使用全局字典
所以我写了这个:
def _coalesce_str(s, candidates):
for candidate in candidates:
if s == candidate:
return candidate
return s
用法示例:
COLORS = 'red', 'green', 'blue', 'orange'
def f():
results = []
for doc in very_large_db_collection():
results.append(_coalesce_str(doc['color'], COLORS))
假设这是我创建大量这些颜色实例的唯一地方。然后,我的手动字符串内部处理对内存占用的影响与内置内部处理相同,但仅限于适当的上下文
在某些方面,这种方法更适合我(在这个特殊的案例中,这与我正在处理的一个现实世界的例子类似),但显然,绕过内置机制根本不适合我。所以我只是好奇是否有一种内置的(或常用的)方法来实现这一点-我在那里找到了很多关于字符串实习的讨论,但在任何地方都找不到这个问题。我在将一些记录从一种格式转换为另一种格式时遇到了这个问题。这个过程涉及到字符串转换的许多步骤,即使使用了这个步骤,仍然需要14GB的内存来表示所有的字符串和字典 我发现,
sys.intern
不能处理Unicode字符串,Unicode字符串不能弱引用,所以我不能使用弱键字典。所以我用了一本普通字典写了:
_objs = {}
def intern(x):
return _objs.setdefault(x, x)
这比sys.intern更好,因为它适用于任何可散列类型。而且可以清除。如果预先填充字典,如果希望字典不累积值,可以使用.get(x,x)
如果需要,人们甚至可以使用大小有限的字典和逐出策略。我在将一些记录从一种格式转换为另一种格式时遇到了这种情况。这个过程涉及到字符串转换的许多步骤,即使使用了这个步骤,仍然需要14GB的内存来表示所有的字符串和字典 我发现,
sys.intern
不能处理Unicode字符串,Unicode字符串不能弱引用,所以我不能使用弱键字典。所以我用了一本普通字典写了:
_objs = {}
def intern(x):
return _objs.setdefault(x, x)
这比sys.intern更好,因为它适用于任何可散列类型。而且可以清除。如果预先填充字典,如果希望字典不累积值,可以使用.get(x,x)
如果需要的话,你甚至可以使用大小有限的字典和驱逐政策。对于一般情况,我会建议与丹一样。既然您事先知道了所有可能的值,那么您也可以构建一个字典
intern = dict(zip(COLORS, COLORS))
并像inter[color]
一样使用它。演示:
>>> COLORS = 'red', 'green', 'blue', 'orange'
>>> intern = dict(zip(COLORS, COLORS))
>>> color = ''.join('red')
>>> color, intern[color]
('red', 'red')
>>> color == intern[color], color is intern[color]
(True, False)
如果出于某种原因,您想限制大小,如Dan在最后提到的,一个简单但好的选择是使用functools.lru\u cache
:
@lru_cache(1000)
def intern(x):
return x
我想说所有的(还有Dan的)都比你自己的版本好,因为dict查找比遍历候选对象更简单、更快(至少在候选对象数量很大的情况下)。对于一般情况,我建议与Dan相同。既然您事先知道了所有可能的值,那么您也可以构建一个字典
intern = dict(zip(COLORS, COLORS))
并像inter[color]
一样使用它。演示:
>>> COLORS = 'red', 'green', 'blue', 'orange'
>>> intern = dict(zip(COLORS, COLORS))
>>> color = ''.join('red')
>>> color, intern[color]
('red', 'red')
>>> color == intern[color], color is intern[color]
(True, False)
如果出于某种原因,您想限制大小,如Dan在最后提到的,一个简单但好的选择是使用functools.lru\u cache
:
@lru_cache(1000)
def intern(x):
return x
我想说所有的(还有Dan的)都比你自己的版本好,因为dict查找比遍历候选对象更简单、更快(至少在候选对象数量很大的情况下)。如果字符串很短,我认为Python会自动对它们进行实习。@Barmar Python 3.8.1告诉我
”。join('aa')是“”。join('aa'))
为False
。而“aa”也是“”。join('aa')
。可能只是字符串文本,而不是动态创建的字符串。是的,就是这样。您是否预先知道所有可能的值,就像您的颜色元组所建议的那样?如果字符串很短,我认为Python会自动对其进行实习。@Barmar Python 3.8.1告诉我“”。join('aa')是“”。join('aa')
是False
。而“aa”也是“”。join('aa')
。可能只是字符串文本,而不是动态创建的字符串。是的,就是这样。您是否提前知道所有可能的值,如您的颜色元组建议的值?