2015-05-12 4 views
2

У меня есть defaultdict(list), который я бы хотел сделать неизменным, чтобы я мог добавлять объекты этого типа в набор. У меня есть идея относительно того, как я могу сделать ее неизменной, но мне потребуется написать несколько строк кода. Нет ли более простого способа сделать это в python?Сделать объект неизменным

Разве это не распространено в python для заполнения, например defaultdict(list), при анализе фрагмента данных перед замораживанием его после завершения разбора?

Его также случай, когда объект может быть типом кортежа, но не может быть использован в качестве ключа Словаря, например:

>>> a = ([1,2],[2,3]) 
>>> type(a) 
<type 'tuple'> 
>>> d = dict() 
>>> d[a] = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'list' 

Почему существует кортеж списков в Python является также то, что я не понимаю.

+0

См. Http://stackoverflow.com/questions/4828080/how-to-make-an-immutable-object-in-python –

+0

также: http://stackoverflow.com/questions/3942825/freeze-in -python –

ответ

1

Чтобы сделать изменяемый объект неизменным, все его изменяемые контейнеры должны быть заменены их неизменяемыми аналогами. Словарь, в котором все значения неизменяемы, может быть сделан неизменным тривиально.

Адаптирование примера из defaultdict(list)documentation:

import collections as coll 
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] 
d = coll.defaultdict(tuple) 
for k, v in s: 
    d[k] = d[k] + (v,) 

print(d) 
# prints 
defaultdict(<class 'tuple'>, {'yellow': (1, 3), 'blue': (2, 4), 'red': (1,)}) 

keys в нашем defaultdict(tuple) неизменен (strings), и значение, а также (tuple), в отличие от defaultdict(list).

Чтобы заморозить этот словарь:

def dict_freeze(d): 
    # This is the trivial one-line function 
    # It assumes the values are of immutable types, i.e. no lists. 
    # It unpacks dict items, sorts and converts to tuple 
    # sorting isn't strictly necessary, but dictionaries don't preserve order 
    # thus we could end up with the following: 
    # d = {'a': 1, 'b': 2} could get frozen as either of the following 
    # (('a', 1), ('b', 2)) != (('b', 2), ('a', 1)) 
    return tuple(sorted(d.items())) 

frozen_d = dict_freeze(d) 
print(frozen_d) 
# prints 
(('blue', (2, 4)), ('red', (1,)), ('yellow', (1, 3))) 

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

+0

", а также значения" Не совсем. Tuple's не мешает их изменениям. Попробуйте поставить что-то изменчивое. – muhuk

+0

Это моя точка зрения. прочитайте начало ответа «Чтобы сделать изменяемый объект неизменным, все его изменяемые контейнеры должны быть заменены их неизменяемыми аналогами». В этом надуманном примере кортежи, о которых идет речь, содержат только целые числа, поэтому «значения в ** this ** defaultdict (кортеж) неизменяемы» –

Смежные вопросы