Q: How can I have the magic `__contains__` method invoked? I have the contains method in my Sentence class that checks if a word is in a sentence(string in my case) 
I tried to check in my functionTesting if hello exist in hello world and I got this error instead:
AttributeError: 'Sentence' object has no attribute 'contains'

here is my code
class Sentence:

    def __init__(self, string):
        self._string = string

    def getSentence(self):
        return self._string

    def getWords(self):
        return self._string.split()

    def getLength(self):
        return len(self._string)

    def getNumWords(self):
        return len(self._string.split())

    def capitalize(self):
        self._string = self._string.upper()

    def punctation(self):
        self._string = self._string + ", "

    def __str__(self):
        return self._string

    def __getitem__(self, k):
        return k

    def __len__(self):
        return self._String

    def __getslice__(self, start, end):
        return self[max(0, i):max(0, j):]

    def __add__(self, other):
        self._string = self._string + other._string
        return self._string

    def __frequencyTable__(self):
        return 0

    def __contains__(self, word):
        if word in self._string:
            return True  # contains function!!##


def functionTesting():
    hippo = Sentence("hello world")
    print(hippo.getSentence())
    print(hippo.getLength())
    print(hippo.getNumWords())
    print(hippo.getWords())

    hippo.capitalize()
    hippo.punctation()

    print(hippo.getSentence())

    print(hippo.contains("hello"))


functionTesting()

How do you call the __contains__ function? Did I make a mistake in the class method function or did I make a mistake in the functionTesting when calling it? I am expecting to get True.

A: Quoting the documentation of __contains__,

Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.
For objects that don't define __contains__(), the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__()

So, it will be invoked when used with the membership testing operator, in, and you should use it like this
print("hello" in hippo)

Important Note: Python 3.x, doesn't have __getslice__ special method at all. Quoting Python 3.0 Change log,

__getslice__(), __setslice__() and __delslice__() were killed. The syntax a[i:j] now translates to a.__getitem__(slice(i, j)) (or __setitem__() or __delitem__(), when used as an assignment or deletion target, respectively).

So, you cannot invoke it with the slicing syntax.


I am expecting to get True.

No. You cannot get True, because you already called hippo.capitalize() before the membership test. So, your self._string is HELLO WORLD,  by the time membership test is happening. So, you will actually get False.
Note 1: In Python, boolean values are represented with True and False. But in your __contains__ function you are returning true which will raise NameError at runtime. You can better write it succinctly like this
def __contains__(self, word):
    return word in self._string

Note 2: Also in your __getslice__ function,
def __getslice__(self, start, end):
    return self[max(0, i):max(0, j):]

you are using i and j which are not defined. Perhaps you wanted to use start and end like this
def __getslice__(self, start, end):
    return self[max(0, start):max(0, end):]


A: You can call the __contains__ function by using in keyword
like 
print "hello" in hippo

