If you are talking strictly about a C # / Java-like interface, then the answer is simple. These are concepts that relate to statically typed languages ββand do not actually apply to a dynamic language such as Python.
The usual pythonic approach is to trust the objects you get and assume that they have the necessary traits that you need. If this is not the case, you can expect runtime errors that can be processed or left to the caller. This is consistent with the general dynamic nature of the language: if something goes wrong, you can expect it to display at runtime.
Java or C # interfaces, on the other hand, are means of checking the necessary preconditions (i.e., objects that have certain methods) at compile time. This (possibly) removes some runtime flexibility to increase the security of compile-time checks.
Note that this does not mean that the concept of any interface does not have a place in a dynamically typed language. In fact, Python has a slightly vague concept of βmeta typesβ - such as iterators - that are often checked against, for example, by checking for the presence of specific method (s):
def process_sequence(seq): if not hasattr(seq, '__iter__'): seq = [seq]
This is conceptually similar to implicit interfaces from the Go language. If you want to have your own iterative option, you simply implement the __iter__
method - without explicitly indicating that you implement it (as in Java, where you inherit the List
class). If someone wants to check if your object is really iterable, he can check if the βcontractβ is actually executed, i.e. Having a __iter__
method. This is what andronicus described in his answer.
As a shameless plugin, I can point to the pyduck library that I am implementing. It aims to simplify (and possibly even standardize) the verification of such "contracts" (through reflection) and makes it somewhat more reliable.
source share