ТипError: Тип расщепления
Я пытаюсь получить список списка кортежей: что-то вроде [ [(1,0),(2,0),(3,0)],[(1,1),(2,1),(3,1)....]]
Я использовал это утверждение
set([(a,b)for a in range(3)]for b in range(3))
Но это дает мне ошибку
TypeError: unhashable type: 'list'
У меня есть 2 вопроса для гуру Python:
a) Когда я смотрю на определение Python Hashable -
"Объект hashable, если он имеет значение хэша, которое никогда не изменяется в течение его жизненного цикла (ему нужен метод хеша())
когда я использовал функцию dir над выражением выше
dir([(a,b)for a in range(3)]for b in range(3))
кажется, что есть __hash__
. Итак, почему я получаю ошибку?
Мне удалось получить [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
используя команду списка:
list(list((a,b) for a in range(3)) for bin range(3))
b) и установите оба параметра Iterable в качестве параметра. Почему один работает (список), а другой не установлен (?)?
Ответы
Ответ 1
Вы создаете вызов set
через set(...)
, а set
нужны хешируемые элементы. У вас нет списка списков. Потому что list arent hashable.
[[(a,b) for a in range(3)] for b in range(3)]
- это список. Это не хешируемый тип. __hash__
, который вы видели в каталоге dir (...), не является методом, а просто None.
Пояснение списка возвращает список, вам не нужно явно использовать список там, просто используйте:
>>> [[(a,b) for a in range(3)] for b in range(3)]
[[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
Попробуйте:
>>> a = {1, 2, 3}
>>> b= [1, 2, 3]
>>> type(a)
<class 'set'>
>>> type(b)
<class 'list'>
>>> {1, 2, []}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> print([].__hash__)
None
>>> [[],[],[]] #list of lists
[[], [], []]
>>> {[], [], []} #set of lists
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Ответ 2
TLDR:
- Вы не можете хешировать список, набор или указание поместить его в наборы
- Вы можете хешировать кортеж, чтобы поместить его в набор.
Пример:
>>> {1, 2, [3, 4]}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> {1, 2, (3, 4)}
set([1, 2, (3, 4)])
Обратите внимание, что хеширование является каким-то рекурсивным, и приведенное выше справедливо для вложенных элементов:
>>> {1, 2, 3, (4, [2, 3])}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Клавиши DICT также могут быть хэшируемыми, поэтому вышеизложенное относится и к клавишам DICT.
Ответ 3
Список не сотрясается, потому что его содержимое может меняться в течение всего срока его службы. Вы можете в любой момент обновить элемент, содержащийся в списке.
В списке не используется хэш для индексирования, поэтому он не ограничивается элементами хеширования.
Ответ 4
Причина реальная, потому что set
не работает, так это то, что она использует хэш-функцию для различения разных значений. Это означает, что набор разрешает только хешируемые объекты. Почему список не хешируется, уже указано.
Ответ 5
... и поэтому вы должны сделать что-то вроде этого:
set(tuple ((a,b) for a in range(3)) for b in range(3))
... и при необходимости конвертировать обратно в список
Ответ 6
Вы обнаружите, что экземпляры list
не предоставляют __hash__
-rather, этот атрибут каждого списка фактически None
(try print [].__hash__
). Таким образом, list
не сотрясается.
Причина, по которой ваш код работает с list
, а не set
, состоит в том, что set
создает один набор элементов без дубликатов, тогда как список может содержать произвольные данные.