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 set
via set(...)
aanroep, en set
heeft 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 set
niet 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 list
geen __hash__
geven — in plaats daarvan is dat kenmerk van elke lijst eigenlijk None
( probeer print [].__hash__
). De list
is dus unhashable.
De reden dat uw code werkt met list
en niet met set
is omdat set
een enkele set items maakt zonder duplicaten, terwijl een lijst dat wel kan willekeurige gegevens bevatten.