[Tutor] unhashable objects (unrelated to previous topic)
Orri Ganel
singingxduck at gmail.com
Mon Mar 28 01:08:41 CEST 2005
Hello all,
I am attempting to implement a LinkedList in Python, and in doing so,
have created a Node class which represents the elements of the
LinkedList. However, since these Nodes have custom-defined __lt__(),
__gt__(), __le__(), __ge__(), __eq__(), and __ne__() methods, they
are, for some reason, unhashable. When I comment out these methods,
Python makes no complaint. But when they are present, 'TypeError:
unhashable instance' is raised when attempting to use a Node as a key
in a dictionary. The full error appears:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in -toplevel-
a.append(0)
File "C:\Documents and Settings\Owner\Desktop\LinkedList.py", line
217, in append
self.lltopl[self.head] = self.pylist[0]
TypeError: unhashable instance
; the relevant code being:
class LinkedList:
def __init__(self,node=None):
"""x.__init__(...) initializes x; see
x.__class__.__doc__ for signature"""
self.length = 0
self.pylist = []
self.lltopl = {}
if node is not None and type(node) == list:
self.head = None
self.tail = None
for i in range(len(node)):
self.append(node[i])
elif node is not None and isinstance(node, LinkedList):
self.head = None
self.tail = None
self.appendlist(node)
else:
if node is not None and not isinstance(node, Node):
self.length += 1
self.pylist.append(Node(node).cargo)
self.head = Node(node)
elif node:
self.length += 1
self.pylist.append(node.cargo)
self.head = node
else: self.head = node
self.tail = None
if len(self.pylist) != 0:
self.lltopl[self.head] = self.pylist[0]
if self.head:
nod = self.head
while nod.next:
self.append(nod.next)
nod = nod.next
self.head.prev = None
def append(self, cargo):
"""Only for the appending of single Nodes.
To append multiple Nodes linked with .next
and .prev, just use appendlist(linkedlist)
method"""
if not isinstance(cargo, Node):
node = Node(cargo)
else: node = cargo
node.next = None
node.prev = None
if not self.head:
self.head = node
self.pylist.append(self.head.cargo)
self.lltopl[self.head] = self.pylist[0]
elif self.tail:
self.tail.next = node
node.prev = self.tail
self.tail = node
self.pylist.append(self.tail.cargo)
self.lltopl[self.tail] = self.pylist[-1]
else:
self.head.next = node
node.prev = self.head
self.tail = node
self.pylist.append(self.tail.cargo)
self.lltopl[self.tail] = self.pylist[-1]
self.length += 1
self.head.prev = None
return True
class Node:
## def __eq__(self, y):
## """x.__eq__(y) <==> x==y"""
## try:
## return self.cargo == y.cargo
## except:
## return self.cargo == y
## def __ge__(self, y):
## """x.__ge__(y) <==> x>=y"""
## try:
## return self.cargo >= y.cargo
## except:
## return self.cargo >= y
## def __gt__(self, y):
## """x.__gt__(y) <==> x>y"""
## try:
## return self.cargo > y.cargo
## except:
## return self.cargo > y
def __init__(self, cargo=None, prev=None, next=None):
self.cargo = cargo
self.prev = prev
self.next = next
## def __le__(self, y):
## """x.__le__(y) <==> x<=y"""
## try:
## return self.cargo <= y.cargo
## except:
## return self.cargo <= y
## def __lt__(self, y):
## """x.__lt__(y) <==> x<y"""
## try:
## return self.cargo < y.cargo
## except:
## return self.cargo < y
## def __ne__(self, y):
## """x.__ne__(y) <==> x!=y"""
## try:
## return self.cargo != y.cargo
## except:
## return self.cargo != y
def __str__(self):
return str(self.cargo)
def cequals(self, node):
if not isinstance(node, Node):
node = Node(node)
if self.cargo == node.cargo:
return True
return False
def equals(self, node):
if self.cequals(node) and self.nequals(node) and
self.pequals(node):
return True
return False
def pequals(self, node):
if not isinstance(node, Node):
if self.prev == node:
return True
elif self.prev == node.prev:
return True
return False
def nequals(self, node):
if not isinstance(node, Node):
if self.next == node:
return True
elif self.next == node.next:
return True
return False
Since the code here is unfinished and not in full form in any case,
its not yet ready for suggestions, however, once I'm done with the
implementation (a matter of finishing the docstrings and making
unittests), I will welcome suggestions and comments. However, if
anyone has any idea why custom comparing methods make an object
unhashable, I'd be grateful.
Thanks in advance,
Orri
--
Email: singingxduck AT gmail DOT com
AIM: singingxduck
Programming Python for the fun of it.
More information about the Tutor
mailing list