set using alternative hash function?

Ethan Furman ethan at stoneleaf.us
Thu Oct 15 19:49:10 CEST 2009


Austin Bingham wrote:
> Yes, I can construct a dict as you
> specify, where all of the keys map to values with name attributes
> equal to the key. My point is that dict doesn't really help me enforce
> that beyond simply letting me set it up; it doesn't care about the
> values at all, just the keys. All that I'm asking for, and I think
> it's been made pretty clear, is a set that let's me define a
> uniqueness criteria function other than hash(). As has been thrashed
> out already, this is not as straightforward as I might have liked.
> 
> To put it in code, I want this:
> 
>   s = set(hash_func = lambda obj: hash(obj.name), eq_func = ...)
>   ...
>   x.name = 'foo'
>   y.name = 'foo'
>   s.add(x)
>   s.add(y) # no-op because of uniqueness criteria
>   assert len(s) == 1
> 
> Austin


I'm feeling really dense about now... What am I missing?

class obj(object):
     def __init__(self, id, value):
         self.id = id
         self.value = value
     def __eq__(self, other):
         if isinstance(other, obj):
             return self.id == other.id
         raise NotImplemented
     def __hash__(self):
         return hash(self.id)
     def __repr__(self):
         return "obj(%s, %s)" % (self.id, self.value)

Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
--> from obj import obj
--> s1 = set()
--> d1 = dict()
--> o1 = obj(17, 'first')
--> o2 = obj(18, 'second')
--> o3 = obj(17, 'third')
--> o1, o2, o3
(obj(17, first), obj(18, second), obj(17, third))
--> s1.add(o1)
--> s1.add(o2)
--> s1.add(o3)
--> d1[o1.id] = o1
--> d1[o2.id] = o2
--> d1[o3.id] = o3
--> s1
set([obj(17, first), obj(18, second)])
--> d1
{17: obj(17, third), 18: obj(18, second)}
-->

Ah ha!  No-op indeed!  If a set already has an item, the new item is 
completely ignored, whereas if a dict already has a key, the new key's 
value replaces the current value already in the dict.

Learn something new everyday!

I'm still not sure I understand your concern about the values in a set, 
though.  Sets keep the first object of a given key, dicts keep the last 
object of a given key; in both cases, all other objects with the same 
key are lost.

So is that the behavior you're wanting, keeping the first object and 
discarding all others?  Or is there something else I'm still missing?

~Ethan~



More information about the Python-list mailing list