Oeufcoque Penteano
Oeufcoque Penteano

Reputation: 603

What are the mechanics of the in operator for lists or hashes of classes in Python?

I am trying to understand how to implement a list or a hash of objects in Python. More specifically, in this question, which was the closest I could get, I saw that by doing:

class MyClass(object):

def __init__(self):
    self.numbers = [1,2,3,4,54]

def __contains__(self, key):
    return key in self.numbers

>>> m = MyClass()
>>> 54 in m
True

I could use the operator in directly on the class to check an attribute inside of it.

My question is an extension of this one. Suppose I have a list or a hash of MyClass objects, that is:

list = [m1,m2,m3]
hash = {m1,m2,m3}

I would like to use something like:

if 54 in list: 
   #do something
if 54 in hash: 
   #do something

What methods are necessary to be defined in MyClass so that the in operator works? I am unsure what in does (if is it a == that would require an __eq or something else). If you happen to know how one would make .index() work in such case I would appreciate as well.

Edit: Sorry the initial question was confusing. I hope I made it clear. I am trying to find an attribute that is part of the class, such as the original example of the other question. But now I am trying to do so inside a list or a hash. In a sense, I would like that by asking if an element is inside a list, it asks if it is inside each element of the list. I am unsure if by using the operator in on a list or a hash it does that, or it compares using ==.

Thank you.

Upvotes: 2

Views: 448

Answers (2)

reptilicus
reptilicus

Reputation: 10397

As @MartijnPieters said, you should overload the __eq__() method. I'm not sure what you mean by the hash/dictionary example you gave.

class MyClass(object):

    def __init__(self):
        self.numbers = [1,2,3,4,54]

    def __contains__(self, key):
        return key in self.numbers

    def __eq__(self, other):
        if other in self.numbers:
            return True
        else:
            return False


m1 = MyClass()
m2 = MyClass()
m3 = MyClass()

test1 = 54 in [m1, m2, m3]
print test1
#True
test2 = 666 in [m1, m2, m3]
print test2
#False

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121844

When in tests for containment, it'll check for equality against your custom type.

In other words, ob in some_sequence can be seen as:

any((ob is contained_ob or ob == contained_ob) for contained_ob in some_sequence)

Two custom classes ob1 and ob2 test as equal if:

  1. They are identical, ob1 is ob2 is True. They are the same object.
  2. If ob1 has an __eq__ method, then ob1.__eq__(ob2) is tested.
  3. If ob1 has no such method, but ob2.__eq__() does exist then ob2.__eq__(ob1) is tried.

You can also define the __ne__() and / or __cmp__() methods to make things a little more complicated, but you generally want to avoid toying with this too much in custom types.

Upvotes: 4

Related Questions