Невозможно рассортировать defaultdict

У меня есть defaultdict, который выглядит так:

dict1 = defaultdict(lambda: defaultdict(int)) 

Проблема в том, что я не могу расчехлить ее с помощью cPickle. Одним из решений, которое я нашел здесь, является использование функции уровня модуля вместо лямбда. Мой вопрос: что такое модульная функция? Как я могу использовать словарь с cPickle?

6 Solutions collect form web for “Невозможно рассортировать defaultdict”

В дополнение к объяснению Мартинна :

Функция уровня модуля – это функция, определенная на уровне модуля, что означает, что это не метод экземпляра класса, он не вложен в другую функцию и является «реальной» функцией с именем, а не с лямбда-функцией ,

Итак, чтобы defaultdict ваш 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) 

Pickle хочет сохранить все атрибуты экземпляра, а экземпляры defaultdict хранят ссылку на вызываемую по default . Pickle рекурсирует по каждому атрибуту экземпляра.

Рассол не справляется с лямбдами; pickle только обрабатывает данные, а не код, а lambdas содержит код. Функции можно мариновать, но точно так же, как определения классов, только если функция может быть импортирована . Можно импортировать функцию, определенную на уровне модуля. Pickle просто хранит строку в этом случае, полный «путь» функции, которую нужно импортировать и ссылаться при повторной загрузке.

Однако вы можете использовать partial выполнение:

 >>> from collections import defaultdict >>> from functools import partial >>> pickle.loads(pickle.dumps(defaultdict(partial(defaultdict, int)))) defaultdict(<functools.partial object at 0x94dd16c>, {}) 

Для этого просто напишите код, который вы хотите написать. Я бы использовал укроп , который может сериализовать 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>, {}) 

В настоящее время я делаю что-то похожее на вопрос 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), но этот шаблон также отвечает на вопрос.

Если вы не заботитесь о сохранении типа 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) 
  • Как получить unpickling для работы с iPython?
  • Сохранять пользовательские атрибуты при подгонке подкласса массива numpy
  • Как распиливать функцию python со своими зависимостями?
  • Травление __setstate__ и __getstate__ не вызывает класс
  • ImportError: нет модуля с именем 'pandas.indexes'
  • Передача вывода маринованного объекта между скриптами python через subprocess.communicate
  • Как реплицировать C # 'byte' и 'Write' в Python
  • Сохранение состояния хэшлиба
  • Python - лучший язык программирования в мире.