В C99 вы можете потребовать, чтобы массив имел как минимум n
элементы:
void print_array (int b [статические n]);
6.7.5.3.7 : объявление параметра как '' массив типа '' должно быть скорректировано на «квалифицированный указатель на тип» '', где типом качества (если есть) являются те, которые указаны в [и] вывода типа массива. Если ключевое слово static также появляется внутри [и] вывода типа массива, то для каждого вызова функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива с по меньшей мере таким количеством элементов, как указано по выражению размера.
В GCC вы можете передать размер массива неявно следующим образом:
void print_array ( int n, int b [n]);
В дополнение к объяснению Martijn :
Функция уровня модуля - это функция, которая определена на уровне модуля, что означает, что это не метод экземпляра класса, он не вложен в другую функцию и является «реальной» функцией с именем, а не с лямбда-функцией.
Итак, чтобы разжечь ваш defaultdict
, создайте его с помощью функции уровня модуля вместо лямбда-функция:
def dd():
return defaultdict(int)
dict1 = defaultdict(dd) # dd is a module-level function
, чем вы можете ее рассортировать
tmp = pickle.dumps(dict1) # no exception
new = pickle.loads(tmp)
dict1 = defaultdict(lambda: defaultdict(int))
cPickle.dump(dict(dict1), file_handle)
работал для меня
Вы можете использовать partial
для выполнения этого:
>>> from collections import defaultdict
>>> from functools import partial
>>> pickle.loads(pickle.dumps(defaultdict(partial(defaultdict, int))))
defaultdict(<functools.partial object at 0x94dd16c>, {})
Pickle хочет сохранить все атрибуты экземпляра, а экземпляры defaultdict
сохраняют ссылку на default
, подлежащую вызову. Рассеивание повторяется над каждым атрибутом экземпляра.
Pickle не может обрабатывать lambdas; pickle только обрабатывает данные, а не код, а lambdas содержит код. Функции можно мариновать , но точно так же, как определения классов, только если функция может быть импортирована . Можно импортировать функцию, определенную на уровне модуля. Pickle просто сохраняет строку в этом случае, полный «путь» функции, которую нужно импортировать и ссылаться при повторной загрузке.
Чтобы сделать это, просто напишите код, который вы хотите написать. Я бы использовал dill , который может сериализовать lambdas и defaultdicts. Dill может сериализовать почти что угодно в python.
>>> import dill
>>> from collections import defaultdict
>>>
>>> dict1 = defaultdict(lambda: defaultdict(int))
>>> pdict1 = dill.dumps(dict1)
>>> _dict1 = dill.loads(pdict1)
>>> _dict1
defaultdict(<function <lambda> at 0x10b31b398>, {})
dill
предоставляет обычные dump
и load
, которые можно использовать так же, как dump
и load
из pickle
. Кроме того, вы можете проверить dill.temp.dump
, который сбрасывается на NamedTemporaryFile
.
– Mike McKerns
7 September 2014 в 13:33
Я сейчас делаю что-то похожее на вопрос poser, однако я использую подкласс defaultdict, который имеет функцию-член, которая используется как default_factory. Для того, чтобы мой код работал правильно (мне нужно, чтобы функция была определена во время выполнения), я просто добавил код для подготовки объекта для травления.
Вместо:
...
pickle.dump(dict, file)
...
Я использую это:
....
factory = dict.default_factory
dict.default_factory = None
pickle.dump(dict, file)
dict.default_factory = factory
...
Это не точный код, который я использовал, поскольку мое дерево - это объект, который создает экземпляры того же типа дерева, что и индексы, (поэтому я использую рекурсивный функция-член для выполнения операций pre / post pickle), но этот шаблон также отвечает на вопрос.
default_factory
маринованного диктата. Если вам больше не нужен завод, вы можете просто установить его на None
и сделать (:
– drevicko
19 September 2014 в 04:41
Если вы не заботитесь о сохранении типа defaultdict, преобразуйте его:
fname = "file.pkl"
for value in nested_default_dict:
nested_default_dict[value] = dict(nested_default_dict[value])
my_dict = dict(nested_default_dict)
with open(fname, "wb") as f:
pickle.dump(my_dict, f) # Now this will work
Я думаю, что это отличная альтернатива, поскольку, когда вы травляете, объект, вероятно, находится в его окончательной форме. .. И если вам действительно нужен тип defaultdict снова, вы можете просто преобразовать обратно после того, как вы распаковываете:
for value in my_dict:
my_dict[value] = defaultdict(type, my_dict[value])
nested_default_dict = defaultdict(type, my_dict)