【问题标题】:Python - What is the cheapest data type to be used as "dummy value" in dictPython - 在dict中用作“虚拟值”的最便宜的数据类型是什么
【发布时间】:2019-02-28 03:26:33
【问题描述】:

我想问什么是最便宜的数据类型(就内存消耗和保存/处理它的成本而言)在 python dict 中用作虚拟值(只有 dict 的键对我很重要,值只是占位符)

例如:

d1 = {1: None, 2: None, 3: None}
d2 = {1: -1, 2: -1, 3: -1}
d3 = {1: False, 2: False, 3: False}

这里只有键 (1, 2, 3) 对我有用,值不是所以它们可以是任何值(仅用作占位符。我想知道我应该在这里使用什么虚拟数据。目前我使用无,但不确定它是否是“最便宜”的。

P.S.,我知道仅存储键的最佳选择可能是使用 Set 而不是 dict(带有虚拟值)。但是,我这样做的原因是因为我想使用 SWIG 在 Python 和 C++ 之间交换数据。现在我已经弄清楚如何使用 SWIG 将 Python dict 作为 std::map 传递给 C++,但是找不到任何关于如何将 Python Set 作为 std::set 传递给 C++...

非常感谢您的帮助/指导!

【问题讨论】:

  • 提示:sys.getsizeof(None) 返回 16。
  • @Jean-FrançoisFabre 但是只有一个None 对象,而且几乎可以肯定无论如何它都存在。所以它的大小无关紧要。
  • @MartinBonner 是的,没关系
  • 您是在问“这些数据结构中的哪一个在 Python 进程的内存中占用的空间最多?”或“当序列化并发送到另一个进程时,这些数据结构中的哪一个在传输过程中具有最小的大小?”?我怀疑这些问题有不同的答案。
  • @Kevin 我认为 OP 不是在谈论跨进程调用——而是在单个进程中在 C++ 和 Python 之间进行调用。

标签: python swig


【解决方案1】:

python 3.4 64位:

>>> import sys
>>> sys.getsizeof(None)
16
>>> sys.getsizeof(False)
24
>>> sys.getsizeof(1)
28
>>> 

所以None 似乎是最好的选择(我只列出了不可变对象,而忽略了字符串和元组)。请注意,这些对象通常被缓存并不重要,因此大小不会乘以字典的元素数量(此外,None保证是单例)

也就是说,与为每个键/值对存储对该对象的引用的成本相比,实际对象的成本可以忽略不计。如果您的字典包含 1000 个值,那么无论值的大小如何,您都有 1000 个要存储的引用。

结论:只要你在任何地方都使用相同的参考,这并不重要,而且由于参考 em> 被存储为每个字典条目的值。

一种可能的替代方法是将set 作为json 表示(然后在list 中)作为指向C++ 端的字符指针传递,它将使用good json parser 对其进行解析。除非您的值是大浮点值(或大整数),否则可以节省内存,因为序列化消除了对象方面。

>>> json.dumps(list(set(range(4,10))))
'[4, 5, 6, 7, 8, 9]'  # hard to beat that in terms of size!

【讨论】:

  • 可能值得指出的是,使用 '[]' 或 {}很多更糟 - 因为这会创建 n 个空列表/字典的副本。
  • @MartinBonner,“创建空列表/字典的 n 个副本”您能否详细说明。谢谢。
  • 如果您使用 a = [] 则不使用 a 作为值。不过尺寸还是比较大的,所以...
  • sys.getsizeof(object()) 在我的系统上也是16
  • 这个a = object() 方法对于创建一个肯定不会在其他地方使用的对象很有用(比如当None 可以作为具有默认参数的方法中的参数时有效)跨度>
【解决方案2】:

您可以使用集合,但 SWIG 似乎只支持将 Python 列表作为 set 参数传递(或使用命名模板),而无需编写您自己的类型映射。示例(Windows):

test.i*

%module test

%include <std_set.i>
%template(seti) std::set<int>;

%inline %{

#include <set>
#include <iostream>
void func(std::set<int> a)
{
    for(auto i : a)
        std::cout << i << std::endl;
}

%}

输出:

>>> import set
>>> s = test.seti([1,1,2,2,3,3])  # pass named template
>>> test.func(s)
1
2
3
>>> test.func([1,2,3,3,4,4])  # pass a list that converts to a set
1
2
3
4
>>> test.func({1,1,2,2,3})   # Actual set doesn't work.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'func', argument 1 of type 'std::set< int,std::less< int >,std::allocator< int > >'

【讨论】:

    猜你喜欢
    • 2011-06-21
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2011-04-29
    • 2011-01-21
    • 1970-01-01
    • 2015-09-10
    相关资源
    最近更新 更多