4

I have a Java background and am studying Python's data model. Specifically, I am curious about how and when special methods (e.g. __add__) get called.

It seems like the Python interpreter may execute these special methods when it encounters certain built-in functions. To take an example from the book "Fluent Python", if you have a class like the following FrenchDeck...

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                                        for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

then __getitem__ will get called when the Python interpreter encounters things like for card in FrenchDeck() or FrenchDeck()[11].

To me, this seems expressive but also extremely vague. How do I determine what built-in functions will call my special methods? There seems to be some implicit mention of mappings between built-ins and special methods in statements of the Python Data Model section like

It is recommended that both mappings and sequences implement the __contains__() method to allow efficient use of the in operator.

But I can't find a clear reference doc with statements like "for user-defined classes, in will use __contains__ if it exists, otherwise it will use __getitem__".

4

From the section on __contains__ :

For objects that don’t define __contains__(), the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__(), see this section in the language reference.

From the linked section:

For user-defined classes which define the __contains__() method, x in y returns True if y.__contains__(x) returns a true value, and False otherwise.

For user-defined classes which do not define __contains__() but do define __iter__(), x in y is True if some value z, for which the expression x is z or x == z is true, is produced while iterating over y. If an exception is raised during the iteration, it is as if in raised that exception.

Lastly, the old-style iteration protocol is tried: if a class defines __getitem__(), x in y is True if and only if there is a non-negative integer index i such that x is y[i] or x == y[i], and no lower integer index raises the IndexError exception. (If any other exception is raised, it is as if in raised that exception).

Here, you can see an example of interpreter C code checking for __iter__ and __getitem__ methods

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.