Python - Какой самый дешевый тип данных для использования в качестве «фиктивного значения» в dict - PullRequest
0 голосов
/ 24 сентября 2018

Я хотел бы спросить, какой самый дешевый тип данных (с точки зрения потребления памяти и стоимости его хранения / обработки) для использования в качестве фиктивного значения в 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), значения не таковы, что они могут быть любым значением (просто используется какзаполнитель. То, что я хочу знать, - это то, что фиктивные данные я должен использовать здесь. Пока я использую Нет, но не уверен, является ли это «самым дешевым».

PS, я знаю лучший вариант для хранениятолько ключи могут использовать Set вместо dict (с фиктивными значениями). Однако, причина, по которой я это делаю, заключается в том, что я хочу обмениваться данными между Python и C ++ с помощью SWIG. А сейчас я понял, как передать Pythonпродиктовать C ++ как std :: map с помощью SWIG, но не могу найти ничего о том, как передать Python Set в C ++ как std :: set ...

Здесь очень важны советы / рекомендации!

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Вы можете использовать набор, но 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 > >'
0 голосов
/ 24 сентября 2018

python 3.4 64bit:

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

Так что None может показаться лучшим выбором (я перечислил только неизменяемые объекты, а также игнорируемые строки и кортежи).Обратите внимание, что это не имеет большого значения, так как эти объекты обычно кешируются, поэтому размер не умножается на количество элементов в вашем словаре (более того, None - это гарантировано в качестве одиночного)

Тем не менее, стоимость фактического объекта пренебрежимо мала по сравнению со стоимостью хранения ссылки на этот объект для каждой пары ключ / значение.Если ваш словарь содержит 1000 значений, у вас есть 1000 ссылок для хранения, независимо от размера значения.

Заключение : это не имеет большого значения, если вы используете то же самоессылка везде, и в любом случае это будет стоить намного больше, чем набор, поскольку ссылки хранятся в качестве значений каждой записи словаря.

Одной из возможных альтернатив будет передача set как json представление (затем в list) как указатель символов на стороне C ++, который будет анализировать его с помощью хорошего парсера json .Если ваши значения не являются большими значениями с плавающей запятой (или огромными целыми числами), это сохранит память полностью, поскольку аспект объекта исключается при сериализации.

>>> json.dumps(list(set(range(4,10))))
'[4, 5, 6, 7, 8, 9]'  # hard to beat that in terms of size!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...