TypeError: Unhashable type

Ik probeer een lijst met tuples te krijgen: zoiets als [ [(1,0),(2,0),(3,0)],[(1,1),(2,1),(3,1)....]]
Ik heb deze verklaring gebruikt

set([(a,b)for a in range(3)]for b in range(3))

Maar ik krijg een foutmelding

TypeError: unhashable type: 'list'

Ik heb 2 vragen voor de Python Guru’s:

a) Als ik kijk naar de Python-definitie van Hashable –

“Een object is hashbaar als het een hash-waarde heeft die tijdens zijn levensduur nooit verandert (het heeft een hash()-methode nodig)”

toen ik de dir-functie gebruikte voor de bovenstaande uitdrukking

dir([(a,b)for a in range(3)]for b in range(3))

het lijkt te zeggen dat de __hash__er is. Dus, waarom krijg ik de fout?

Ik heb [[(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1), (2, 1)], [(0, 2), (1, 2), (2, 2)]]
door het lijstcommando te gebruiken:

list(list((a,b) for a in range(3)) for bin range(3))

b)list en set nemen beide Iterable als parameter. Hoe komt het dat de ene werkt (lijst) en de andere niet (set)?


Antwoord 1, autoriteit 100%

Je maakt een setvia set(...)aanroep, en setheeft hashbare items nodig. U kunt geen reeks lijsten hebben. Omdat de lijst niet hashbaar is.

[[(a,b) for a in range(3)] for b in range(3)]is een lijst. Het is geen hash-type. De __hash__die je zag in dir(…) is geen methode, het is gewoon Geen.

Een lijstbegrip retourneert een lijst, u hoeft de lijst daar niet expliciet te gebruiken, gebruik gewoon:

>>> [[(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)]]

Probeer deze:

>>> 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'

Antwoord 2, autoriteit 45%

TLDR:

– Je kunt een lijst, een set of een dictaat niet hashen om dat in sets te zetten

– Je kunt een tuple hashen om het in een set te plaatsen.

Voorbeeld:

>>> {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)])

Houd er rekening mee dat hashing op de een of andere manier recursief is en het bovenstaande geldt voor geneste items:

>>> {1, 2, 3, (4, [2, 3])}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Dict-sleutels zijn ook hashbaar, dus het bovenstaande geldt ook voor dict-sleutels.


Antwoord 3, autoriteit 24%

Een lijst kan niet worden gehasht omdat de inhoud ervan tijdens de levensduur kan veranderen. U kunt een item in de lijst op elk moment bijwerken.

Een lijst gebruikt geen hash voor indexering, dus het is niet beperkt tot hashbare items.


Antwoord 4, autoriteit 21%

De echtereden waarom setniet werkt, is het feit dat het de hash-functie gebruikt om verschillende waarden te onderscheiden. Dit betekent dat sets alleen hashbare objecten toestaan. Waarom een lijst niet hashable is, is al aangegeven.


Antwoord 5, autoriteit 18%

… en dus zou je zoiets als dit moeten doen:

set(tuple ((a,b) for a in range(3)) for b in range(3))

… en indien nodig terug converteren naar lijst


Antwoord 6, autoriteit 3%

U zult zien dat exemplaren van listgeen __hash__geven — in plaats daarvan is dat kenmerk van elke lijst eigenlijk None( probeer print [].__hash__). De listis dus unhashable.

De reden dat uw code werkt met listen niet met setis omdat seteen enkele set items maakt zonder duplicaten, terwijl een lijst dat wel kan willekeurige gegevens bevatten.

Other episodes