Types that define `__eq__` are unhashable?
Yes, if you define __eq__
, the default __hash__
(namely, hashing the address of the object in memory) goes away. This is important because hashing needs to be consistent with equality: equal objects need to hash the same.
The solution is simple: just define __hash__
along with defining __eq__
.
Add __hash__ and __eq__ to imported type (tkinter DoubleVar) to put it in a dictionary
You can assign methods (including __hash__
and similar) to existing classes:
# a class without explicit __hash__
class A:
def __init__(self,i):
self.i = i
a1 = A(1)
print(hash(a1)) # default hash
# define a "free" function ...
def A_hash(self):
return hash(self.i)
# ... and "binds" it to class A
A.__hash__ = A_hash
a2 = A(1)
print(hash(a2)) # new it has user defined hash
EDIT: updated code with initially unhashable object and dictionary test:
# a class without explicit __hash__
class A(list):
def __init__(self,i):
self.i = i
a1 = A(1)
# print(hash(a1)) # would be TypeError: unhashable type: 'A'
# define a "free" function ...
def A_hash(self):
return hash(self.i)
# ... and "binds" it to class A
A.__hash__ = A_hash
a2 = A(1)
print(hash(a2)) # new it has user defined hash
d = {a2:1}
print(d)
What makes a user-defined class unhashable?
Simply setting the __hash__
method to that of the tuple
class is not enough. You haven't actually told it how to hash any differently. tuples are hashable because they are immutable. If you really wanted to make you specific example work, it might be like this:
class X2(list):
def __hash__(self):
return hash(tuple(self))
In this case you are actually defining how to hash your custom list subclass. You just have to define exactly how it can generate a hash. You can hash on whatever you want, as opposed to using the tuple's hashing method:
def __hash__(self):
return hash("foobar"*len(self))
How to overcome TypeError: unhashable type: 'list'
As indicated by the other answers, the error is to due to k = list[0:j]
, where your key is converted to a list. One thing you could try is reworking your code to take advantage of the split
function:
# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
d = {}
# Here we use readlines() to split the file into a list where each element is a line
for line in f.readlines():
# Now we split the file on `x`, since the part before the x will be
# the key and the part after the value
line = line.split('x')
# Take the line parts and strip out the spaces, assigning them to the variables
# Once you get a bit more comfortable, this works as well:
# key, value = [x.strip() for x in line]
key = line[0].strip()
value = line[1].strip()
# Now we check if the dictionary contains the key; if so, append the new value,
# and if not, make a new list that contains the current value
# (For future reference, this is a great place for a defaultdict :)
if key in d:
d[key].append(value)
else:
d[key] = [value]
print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
Note that if you are using Python 3.x, you'll have to make a minor adjustment to get it work properly. If you open the file with rb
, you'll need to use line = line.split(b'x')
(which makes sure you are splitting the byte with the proper type of string). You can also open the file using with open('filename.txt', 'rU') as f:
(or even with open('filename.txt', 'r') as f:
) and it should work fine.
TypeError: unhashable type: 'list' when using built-in set function
Sets require their items to be hashable. Out of types predefined by Python only the immutable ones, such as strings, numbers, and tuples, are hashable. Mutable types, such as lists and dicts, are not hashable because a change of their contents would change the hash and break the lookup code.
Since you're sorting the list anyway, just place the duplicate removal after the list is already sorted. This is easy to implement, doesn't increase algorithmic complexity of the operation, and doesn't require changing sublists to tuples:
def uniq(lst):
last = object()
for item in lst:
if item == last:
continue
yield item
last = item
def sort_and_deduplicate(l):
return list(uniq(sorted(l, reverse=True)))
Unhashable Type error when modifying SqlAlchemy Models
I have a "solution" for this, but I want to make sure its a viable solution and not an unstable hack.
I realize that adding the ne and eq functions to the class requires the hash function to be added in order for the model to be hashable. So this is now working:
class Role(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
def __init__(self, name, desc):
self.name = name
self.description = desc
def __repr__(self):
return '<Role: {}>'.format(str(self.name))
def __eq__(self, other):
return (self.name == other or
self.name == getattr(other, 'name', None))
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash(self.name)
Let me know if I've done this properly, thanks!
Related Topics
Modular Multiplicative Inverse Function in Python
How to Check That Multiple Keys Are in a Dict in a Single Pass
Writing Utf-8 String to MySQL with Python
Matplotlib: How to Prevent X-Axis Labels from Overlapping
Python Argparse - Add Argument to Multiple Subparsers
Pandas Finding Local Max and Min
How to Strip the Whitespace from Pandas Dataframe Headers
Handling Multiple Requests in Flask
Overloaded Functions in Python
Identifying Objects, Why Does the Returned Value from Id(...) Change
Convert Timedelta to Total Seconds
How to Fix the "Element Not Interactable" Exception
How to Concatenate Two Dataframes Without Duplicates
Importing Flask.Ext Raises Modulenotfounderror
How to Check If a Column Exists in Pandas
Python: One Try Multiple Except
Read a Small Random Sample from a Big CSV File into a Python Data Frame