> For the complete documentation index, see [llms.txt](https://python-self-driving.gitbook.io/self-driving/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://python-self-driving.gitbook.io/self-driving/python/interface.md).

# Interface

An interface, for an object, is a set of methods and attributes on that object.

In Python, we can use an abstract base class to define and enforce an interface.

### Using an Abstract Base Class

For example, say we want to use one of the abstract base classes from the `collections` module:

```
import collections
class MySet(collections.Set):
    pass
```

If we try to use it, we get an `TypeError` because the class we created does not support the expected behavior of sets:

```
>>> MySet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__
```

So we are required to implement at *least* `__contains__`, `__iter__`, and `__len__`. Let's use this implementation example from the [documentation](https://docs.python.org/2/library/collections.html#collections-abstract-base-classes):

```
class ListBasedSet(collections.Set):
    """Alternate set implementation favoring space over speed
    and not requiring the set elements to be hashable. 
    """
    def __init__(self, iterable):
        self.elements = lst = []
        for value in iterable:
            if value not in lst:
                lst.append(value)
    def __iter__(self):
        return iter(self.elements)
    def __contains__(self, value):
        return value in self.elements
    def __len__(self):
        return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2
```

### Implementation: Creating an Abstract Base Class

We can create our own Abstract Base Class by setting the metaclass to `abc.ABCMeta` and using the `abc.abstractmethod` decorator on relevant methods. The metaclass will be add the decorated functions to the `__abstractmethods__` attribute, preventing instantiation until those are defined.

```
import abc
```

For example, "effable" is defined as something that can be expressed in words. Say we wanted to define an abstract base class that is effable, in Python 2:

```
class Effable(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')
```

Or in Python 3, with the slight change in metaclass declaration:

```
class Effable(object, metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')
```

Now if we try to create an effable object without implementing the interface:

```
class MyEffable(Effable): 
    pass
```

and attempt to instantiate it:

```
>>> MyEffable()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__
```

We are told that we haven't finished the job.

Now if we comply by providing the expected interface:

```
class MyEffable(Effable): 
    def __str__(self):
        return 'expressable!'
```

we are then able to use the concrete version of the class derived from the abstract one:

```
>>> me = MyEffable()
>>> print(me)
expressable!
```

There are other things we could do with this, like register virtual subclasses that already implement these interfaces, but I think that is beyond the scope of this question. The other methods demonstrated here would have to adapt this method using the `abc` module to do so, however.

### Conclusion

We have demonstrated that the creation of an Abstract Base Class defines interfaces for custom objects in Python.
