Python unhashable type: 'OrderedDict' - python

I am not at all unfamiliar with the concept of:
TypeError: unhashable type: 'OrderedDict'
But I can not understand how the following line of codes can produce such a stack-trace.
89: #staticmethod
90: def diff(var1, var2, path=[], level=0, curpath=[]):
...
101: elif isinstance(var1, list) and isinstance(var2, list):
102: l1s = set(var1)
103: l2s = set(var2)
104: retlist = []
File "myFile.py", line 102, in diff
l1s = set(var1)
TypeError: unhashable type: 'OrderedDict'
How can line 102, in the above code throw such an exception?

Some data structures (most notably dicts and sets) require objects they contain (keys in the case of dictionaries, items in the case of sets) to implement the __hash__() magic method, so that calling hash(obj) returns a value.
This is required to optimize the structure, and together with immutability to help guarantee uniqueness of contained objects.
In your case, var1 contains some object that is not hashable (it does not implement hash()). This object is an OrderedDict, which is a mutable object and is not hashable by design.
As an example of an other object type which is mutable and not hashable by design, consider list and this example:
>>> L = [1, 2, 3]
>>> set([L])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(L)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
If you're using set() to ensure uniqueness then you must go some other way, though it's not clear from your question.

dict(including OrderedDict) in python are mutable containers.
If a dict was hashed, its hash value would be changed as long as you changed the dict's contents.

Sets in python are based on hashes. OrderedDicts are not hashable.

Related

What is difference between tuples and lists [duplicate]

This question already has answers here:
What's the difference between lists and tuples?
(22 answers)
Closed 21 days ago.
I am trying to understand the difference between tuples and lists
I was trying to use tuples and lists in a piece of my code, and not realising the difference between tuple and list, could someone please tell me difference,
Thanks,
Gops
Both list and tuple are used to store multiple items within a single collection, but there is a key difference tuple is immutable while list is not. Mutability means the ability to modify the object afterward.
# Here we can modify my_list just fine
>>> my_list = ["hello"]
>>> my_list[0] = "world"
>>> print(my_list)
['world']
# But modifying my_tuple leads to an error
>>> my_tuple = ('hello',)
>>> my_tuple[0] = 'world'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> print(my_tuple)
('h', 'e', 'l', 'l', 'o')
You might think to ask why use tuples at all if we can't mutate them. Wouldn't it be better to just have everything be more flexible?
Well, there are things that tuples can do that lists cannot do such as acting as keys for a dictionary. This is a very useful trick for things like points as keys.
>>> my_dict = {("hello", "world"): "foo"}
>>> my_dict[("hello", "world")]
'foo'
If you try to do the same with lists, you get this error. The error message hints at the key difference. Lists cannot be hashed but tuples can be hashed.
>>> my_dict = {["hello", "world"]: "foo"}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

What does Tuple[Hashable] mean in Python?

I came across the following piece of code:
def func(self, v: Tuple[Hashable]):
...
I know v: Tuple would mean variable v must be of type Tuple, but what does Tuple[Hashable] mean? Isn't a tuple in Python always hashable?
A tuple is only hashable if the values in the tuple are hashable themselves.
>>> hash((1,2))
-3550055125485641917
>>> hash(([1],2))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Why isinstance() not recognising list as a type?

Very basic but I can't think what I'm doing wrong so hoping maybe it's a syntax change I'm not yet aware of.
This line:
if isinstance(x, list):
Throws this error:
TypeError: isinstance() arg 2 must be a type or tuple of types
So why isinstance() not recognising list as a type?
You probably overwritten list somewhere in your program:
>>> isinstance("", list)
False
>>> list = 123
>>> isinstance("", list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types
>>>

Python: Adding dictionary value pair only if they are Unique. If they are already present, I need to print the dictionay values

class VoqConnIngressList:
def addEntry(self,voqID, core, nofVoqs, remoteVOQconnector, remoteModID, unitID):
key = [voqID+","+remoteModID]
if key not in self.dictOfVoqs:
self.dictOfVoqs[voqID+","+remoteModID] = [voqID, core, nofVoqs, remoteVOQconnector, remoteModID, unitID]
else:
print("Entry already present")
voqConnIngressList.addEntry(10, 30, 40, 50, 60, 1)
voqConnIngressList.addEntry(10, 30, 40, 50, 60, 1)
In this core If it detects duplicates. then I should print message saying it is duplicate.
When I types this code, I am getting the below error
if key not in self.dictOfVoqs: TypeError: unhashable type: 'list'
You don't need those square braces [] for defining your key variable. It becomes a list when you add those. A membership check on the dict will run through the dictionary keys of which a list is not hashable and does not qualify as a candidate/potential key:
>>> [] in {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Just replace that line with:
key = voqID + "," + remoteModID
In the second line of your code key = [voqID+","+remoteModID], you are making the key a list. Keys cannot be lists. Remove the square brackets. key = voqID+","+remoteModID
Not sure if it's a difference between the python versions, but...
A key in a dictionary needs to be hashable, and a list is not hashable (but a string would be).
Your key
key = [voqID+","+remoteModID]
is a list, because of the []
Just make it a string.

Set function error in Python3: list is unhashable type

When run the following code in a scratch file, everything works:
x = [1,1,1]
print(set(x))
> {1}
And yet when I run the following code
class MyClass(object):
def __init__(self):
self.mylist = []
def train(self,vector):
self.mylist.append(vector)
self.mylist = list(set(self.mylist))
I get the error, TypeError: unhashable type: 'list'.
What's the problem here?
When you issue
x = [1,1,1]
set(x)
you are building a set from the elements in x, which is fine because the elements of x are of type int and therefore immutable.
However, mylist is a list of lists (because your vector objects are lists). The problem here is that the lists inside mylist are mutable and therefore cannot be hashed. That's why python refuses to build the set.
You can solve this issue by casting your vector lists to tuple. tuples are immutable and therefore Python has no problem with building a set from a list of tuple objects.
Demo:
>>> lst = [[1,2], [3,4]]
>>> set(lst)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> set(map(tuple, lst))
set([(1, 2), (3, 4)])
This is correct. List is unhashable because it's mutable. Use a tuple instead.

Categories

Resources