Re: set using alternative hash function?

Discussion in 'Python' started by Chris Rebert, Oct 15, 2009.

  1. Chris Rebert

    Chris Rebert Guest

    On Thu, Oct 15, 2009 at 4:24 AM, Austin Bingham
    <> wrote:
    > If I understand things correctly, the set class uses hash()
    > universally to calculate hash values for its elements. Is there a
    > standard way to have set use a different function? Say I've got a
    > collection of objects with names. I'd like to create a set of these
    > objects where the hashing is done on these names. Using the __hash__
    > function seems inelegant because it means I have to settle on one type
    > of hashing for these objects all of the time, i.e. I can't create a
    > set of them based on a different uniqueness criteria later. I'd like
    > to create a set instance that uses, say, 'hash(x.name)' rather than
    > 'hash(x)'.
    >
    > Is this possible? Am I just thinking about this problem the wrong way?
    > Admittedly, I'm coming at this from a C++/STL perspective, so perhaps
    > I'm just missing the obvious. Thanks for any help on this.


    You could use wrapper objects that define an appropriate __hash__():

    #*completely untested*
    class HashWrapper(object):
    def __init__(self, obj, criteria):
    self._wrapee = obj
    self._criteria = criteria

    #override __hash__() / hash()
    def __hash__(self):
    return hash(self._criteria(self._wrapee))

    #proxying code
    def __getattr__(self, name):
    return getattr(self._wrapee, name)

    def __setattr__(self, name, val):
    setattr(self._wrapee, name, val)

    #example
    def name_of(obj):
    return obj.name

    def name_and_serial_num(obj):
    return obj.name, obj.serial_number

    no_same_names = set(HashWrapper(obj, name_of) for obj in some_collection)
    no_same_name_and_serial = set(HashWrapper(obj, name_and_serial_num)
    for obj in some_collection)

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Oct 15, 2009
    #1
    1. Advertising

  2. Chris Rebert wrote:

    > On Thu, Oct 15, 2009 at 4:24 AM, Austin Bingham
    > <> wrote:
    >> If I understand things correctly, the set class uses hash()
    >> universally to calculate hash values for its elements. Is there a
    >> standard way to have set use a different function? Say I've got a
    >> collection of objects with names. I'd like to create a set of these
    >> objects where the hashing is done on these names. Using the __hash__
    >> function seems inelegant because it means I have to settle on one type
    >> of hashing for these objects all of the time, i.e. I can't create a
    >> set of them based on a different uniqueness criteria later. I'd like
    >> to create a set instance that uses, say, 'hash(x.name)' rather than
    >> 'hash(x)'.
    >>
    >> Is this possible? Am I just thinking about this problem the wrong way?
    >> Admittedly, I'm coming at this from a C++/STL perspective, so perhaps
    >> I'm just missing the obvious. Thanks for any help on this.

    >
    > You could use wrapper objects that define an appropriate __hash__():
    >
    > #*completely untested*
    > class HashWrapper(object):
    > def __init__(self, obj, criteria):
    > self._wrapee = obj
    > self._criteria = criteria
    >
    > #override __hash__() / hash()
    > def __hash__(self):
    > return hash(self._criteria(self._wrapee))
    >
    > #proxying code
    > def __getattr__(self, name):
    > return getattr(self._wrapee, name)
    >
    > def __setattr__(self, name, val):
    > setattr(self._wrapee, name, val)


    This doesn't work for conflicting elements, as the __eq__-method isn't
    overriden.

    Diez
     
    Diez B. Roggisch, Oct 15, 2009
    #2
    1. Advertising

  3. Chris Rebert

    Chris Rebert Guest

    On Thu, Oct 15, 2009 at 5:22 AM, Diez B. Roggisch <> wrote:
    > Chris Rebert wrote:
    >
    >> On Thu, Oct 15, 2009 at 4:24 AM, Austin Bingham
    >> <> wrote:
    >>> If I understand things correctly, the set class uses hash()
    >>> universally to calculate hash values for its elements. Is there a
    >>> standard way to have set use a different function? Say I've got a
    >>> collection of objects with names. I'd like to create a set of these
    >>> objects where the hashing is done on these names. Using the __hash__
    >>> function seems inelegant because it means I have to settle on one type
    >>> of hashing for these objects all of the time, i.e. I can't create a
    >>> set of them based on a different uniqueness criteria later. I'd like
    >>> to create a set instance that uses, say, 'hash(x.name)' rather than
    >>> 'hash(x)'.
    >>>
    >>> Is this possible? Am I just thinking about this problem the wrong way?
    >>> Admittedly, I'm coming at this from a C++/STL perspective, so perhaps
    >>> I'm just missing the obvious. Thanks for any help on this.

    >>
    >> You could use wrapper objects that define an appropriate __hash__():
    >>
    >> #*completely untested*
    >> class HashWrapper(object):
    >>     def __init__(self, obj, criteria):
    >>         self._wrapee = obj
    >>         self._criteria = criteria
    >>
    >>     #override __hash__() / hash()
    >>     def __hash__(self):
    >>         return hash(self._criteria(self._wrapee))
    >>
    >>     #proxying code
    >>     def __getattr__(self, name):
    >>         return getattr(self._wrapee, name)
    >>
    >>     def __setattr__(self, name, val):
    >>         setattr(self._wrapee, name, val)

    >
    > This doesn't work for conflicting elements, as the __eq__-method isn't
    > overriden.


    Indeed. Good catch. :)
    This is why I mark code as "completely untested".

    Cheers,
    Chris
     
    Chris Rebert, Oct 15, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Austin Bingham

    set using alternative hash function?

    Austin Bingham, Oct 15, 2009, in forum: Python
    Replies:
    20
    Views:
    723
    Carl Banks
    Oct 17, 2009
  2. Austin Bingham

    Re: set using alternative hash function?

    Austin Bingham, Oct 15, 2009, in forum: Python
    Replies:
    6
    Views:
    295
    Austin Bingham
    Oct 15, 2009
  3. rp
    Replies:
    1
    Views:
    556
    red floyd
    Nov 10, 2011
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    640
    David A. Black
    Jul 2, 2008
  5. Patrick Put
    Replies:
    9
    Views:
    141
    Robert Klemme
    Feb 3, 2009
Loading...

Share This Page