Sets and Membership Tests

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JKPeck

    #1

    Sets and Membership Tests

    I would like to be able use sets where the set members are objects of a
    class I wrote.
    I want the members to be distinguished by some of the object content,
    but I have not figured out how a set determines whether two (potential)
    elements are identical. I tried implementing __eq__ and __ne__ and
    __hash__ to make objects with identical content behave as identical for
    set membership, but so far no luck.

    I could subclass set if necessary, but I still don't know what I would
    need to override.

    TIA for any advice you can offer.

  • Klaas

    #2
    Re: Sets and Membership Tests


    JKPeck wrote:
    I would like to be able use sets where the set members are objects of a
    class I wrote.
    I want the members to be distinguished by some of the object content,
    but I have not figured out how a set determines whether two (potential)
    elements are identical. I tried implementing __eq__ and __ne__ and
    __hash__ to make objects with identical content behave as identical for
    set membership, but so far no luck.
    __eq__ and __hash__ are necessary and sufficient. Code?

    -Mike

    Comment

    • Nick Vatamaniuc

      #3
      Re: Sets and Membership Tests

      JK,

      You are correct to implement __hash__ and __eq__. The problem is how
      you implemented them. Usually your __eq__ method should compare the
      necessary attributes of the objects for equality. The __hash__ should
      return a 32-bit integer. Your best bet is probably to return a hash of
      hashes of your attributes that are used in equality comparison. What
      this means is that your attributes used to produce the __hash__ should
      also be hashable. This is important yet not immediatly obvious. So you
      could for example return hash( (attribute1, attribute2, attribute3) ),
      where attribute1, attribute2, attribute3 are all hashable.
      Of course, you provided no code and no error messages (the
      'SoFarNoLuck' exception is not descriptive enough ; )

      Hope this helps



      JKPeck wrote:
      I would like to be able use sets where the set members are objects of a
      class I wrote.
      I want the members to be distinguished by some of the object content,
      but I have not figured out how a set determines whether two (potential)
      elements are identical. I tried implementing __eq__ and __ne__ and
      __hash__ to make objects with identical content behave as identical for
      set membership, but so far no luck.
      >
      I could subclass set if necessary, but I still don't know what I would
      need to override.
      >
      TIA for any advice you can offer.

      Comment

      • JKPeck

        #4
        Re: Sets and Membership Tests

        Thanks for the advice. Once assured that __hash__ etc was the right
        route, I found that using hash() instead of object.__hash__ () gave me
        stable hash valules. (I am hashing strings that I know to be unique.)

        The "no luck" situation was that a set would accept the same object
        multiple times, not recognizing that it was truly the same object.


        Nick Vatamaniuc wrote:
        JK,
        >
        You are correct to implement __hash__ and __eq__. The problem is how
        you implemented them. Usually your __eq__ method should compare the
        necessary attributes of the objects for equality. The __hash__ should
        return a 32-bit integer. Your best bet is probably to return a hash of
        hashes of your attributes that are used in equality comparison. What
        this means is that your attributes used to produce the __hash__ should
        also be hashable. This is important yet not immediatly obvious. So you
        could for example return hash( (attribute1, attribute2, attribute3) ),
        where attribute1, attribute2, attribute3 are all hashable.
        Of course, you provided no code and no error messages (the
        'SoFarNoLuck' exception is not descriptive enough ; )
        >
        Hope this helps
        >
        >
        >
        JKPeck wrote:
        I would like to be able use sets where the set members are objects of a
        class I wrote.
        I want the members to be distinguished by some of the object content,
        but I have not figured out how a set determines whether two (potential)
        elements are identical. I tried implementing __eq__ and __ne__ and
        __hash__ to make objects with identical content behave as identical for
        set membership, but so far no luck.

        I could subclass set if necessary, but I still don't know what I would
        need to override.

        TIA for any advice you can offer.

        Comment

        • Alex Martelli

          #5
          Re: Sets and Membership Tests

          JKPeck <JKPeck@gmail.c omwrote:
          Thanks for the advice. Once assured that __hash__ etc was the right
          route, I found that using hash() instead of object.__hash__ () gave me
          stable hash valules. (I am hashing strings that I know to be unique.)
          >
          The "no luck" situation was that a set would accept the same object
          multiple times, not recognizing that it was truly the same object.
          Your problem may have been exactly that you were misunderstandin g the
          nature and functionality of object.__hash__ :
          >>x='guess what'
          >>id(x)
          360720
          >>object.__hash __(x)
          360720

          As you see, what it does is return the id() of the object (that's how
          objects are hashed -- if they don't implement __eq__ or __cmp__,
          equality comparisons also go to the id()'s, so things work;-) -- unless
          their type/class overrides __hash__). Of course, by going directly to
          object.__hash__ you're explicitly *avoiding* the override, so...


          Alex

          Comment

          • Nick Vatamaniuc

            #6
            Re: Sets and Membership Tests

            JK,
            As a general rule, let Python call the "magic" __method__ methods
            behind the scenes. So don't call obj.__hash()__ or obj.__len__ or
            obj.__le__ just use hash(obj), len(obj) or <=. Of course there are
            exceptions, for example when calling the __init__() method of a
            supercalass inside the __init__ method of your class and perhaps a few
            others...
            Nick V.


            JKPeck wrote:
            Thanks for the advice. Once assured that __hash__ etc was the right
            route, I found that using hash() instead of object.__hash__ () gave me
            stable hash valules. (I am hashing strings that I know to be unique.)
            >
            The "no luck" situation was that a set would accept the same object
            multiple times, not recognizing that it was truly the same object.
            >
            >
            Nick Vatamaniuc wrote:
            JK,

            You are correct to implement __hash__ and __eq__. The problem is how
            you implemented them. Usually your __eq__ method should compare the
            necessary attributes of the objects for equality. The __hash__ should
            return a 32-bit integer. Your best bet is probably to return a hash of
            hashes of your attributes that are used in equality comparison. What
            this means is that your attributes used to produce the __hash__ should
            also be hashable. This is important yet not immediatly obvious. So you
            could for example return hash( (attribute1, attribute2, attribute3) ),
            where attribute1, attribute2, attribute3 are all hashable.
            Of course, you provided no code and no error messages (the
            'SoFarNoLuck' exception is not descriptive enough ; )

            Hope this helps



            JKPeck wrote:
            I would like to be able use sets where the set members are objects of a
            class I wrote.
            I want the members to be distinguished by some of the object content,
            but I have not figured out how a set determines whether two (potential)
            elements are identical. I tried implementing __eq__ and __ne__ and
            __hash__ to make objects with identical content behave as identical for
            set membership, but so far no luck.
            >
            I could subclass set if necessary, but I still don't know what I would
            need to override.
            >
            TIA for any advice you can offer.

            Comment

            Working...