Most of the abstract base classes that exist in the Python standard library live in the collections module. One of the simplest ones is the Container class. Let's inspect it in the Python interpreter to see what methods this class requires:
>>> from collections import Container >>> Container.__abstractmethods__ frozenset(['__contains__'])
So, the Container class has exactly one abstract method that needs to be implemented, __contains__. You can issue help(Container.__contains__) to see what the function signature should look like:
Help on method __contains__ in module _abcoll:
__contains__(self, x) unbound _abcoll.Container method
We can see that __contains__ needs to take a single argument. Unfortunately, the help file doesn't tell us much about what that argument should be, but it's pretty obvious from the name of the ABC and the single method it implements that this argument is the value the user is checking to see whether the container holds.
This method is implemented by list, str, and dict to indicate whether or not a given value is in that data structure. However, we can also define a silly container that tells us whether a given value is in the set of odd integers:
class OddContainer: def __contains__(self, x): if not isinstance(x, int) or not x % 2: return False return True
Here's the interesting part: we can instantiate an OddContainer object and determine that, even though we did not extend Container, the class is a Container object:
>>> from collections import Container >>> odd_container = OddContainer() >>> isinstance(odd_container, Container) True >>> issubclass(OddContainer, Container) True
And that is why duck typing is way more awesome than classical polymorphism. We can create is a relationships without the overhead of writing the code to set up inheritance (or worse, multiple inheritance).
One cool thing about the Container ABC is that any class that implements it gets to use the in keyword for free. In fact, in is just syntax sugar that delegates to the __contains__ method. Any class that has a __contains__ method is a Container and can therefore be queried by the in keyword, for example:
>>> 1 in odd_container True >>> 2 in odd_container False >>> 3 in odd_container True >>> "a string" in odd_container False