Inspired by a great question (and bunch of great answers) from here.
Does the statement "Code against an interface, not an object" have any significance in Python?
I'm looking for answers like the ones in the Original Question but with Python snippets and thoughts.
No, python does not have any equivalent of interfaces . Since Python does support multiple inheritance, you can easily emulate the equivalence of interfaces.
Implicitly they are ' public abstract '. Since Java 8, methods can be implemented ( can have a code body ) in an interface if only if it is declared static or default. Abstract methods cannot have a body; all they can have is a method signature as shown in the example above.
Why Python Does Not Support Interfaces? In statically typed languages like Java or C#, type checking happens at compile time. Python however, is a dynamically typed language, which means that there are no compile-time guarantees for type-safety, so an interface would not be that useful.
Unfortunately, Python doesn't have interfaces, or at least, not quite built into the language. Enter Python's abstract base class, or, cutely, ABC. Functionally, abstract base classes let you define a class with abstract methods, which all subclasses must implement in order to be initialized.
"Code against an interface, not an object" doesn't make literal sense in Python because the language doesn't have an interface feature. The rough Python equivalent is "use duck typing." If you want to see if an object is a duck, in other words, you should check to see whether it has a quack()
method, or better yet try to quack()
and provide appropriate error handling, not test to see if it is an instance of Duck
.
Common duck types in Python are files (well, really, file-like objects), mappings (dict
-like objects), callables (function-like objects), sequences (list
-like objects), and iterables (things you can iterate over, which can be containers or generators).
As an example, Python features that want a file will generally be happy to accept an object that implements the methods of file
it needs; it needn't be derived from the file
class. To use an object as standard out, for example, the main thing it is going to need is a write()
method (and maybe flush()
and close()
, which needn't actually do anything). Similarly, a callable is any object that has a __call__()
method; it needn't be derived from the function type (in fact, you can't derive from the function type).
You should take a similar approach. Check for the methods and attributes you need for what you're going to do with an object. Better yet, document what you expect and assume that whoever is calling your code is not a total doofus. (If they give you an object you can't use, they will certainly figure that out quickly enough from the errors they get.) Test for specific types only when necessary. It is necessary at times, which is why Python gives you type()
, isinstance()
, and issubclass()
, but be careful with them.
Python's duck typing is equivalent to "code against an interface, not an object" in the sense that you're advised not to make your code too reliant on an object's type, but rather to see whether it has the interface you need. The difference is that in Python, "interface" just means an informal bundle of attributes and methods of an object that provide a certain behavior, rather than a language construct specifically named interface
.
You can formalize Python "interfaces" to some extent using the abc
module, which allows you to declare that a given class is a subclass of a given "abstract base class" (interface) using any criteria you desire, such as "it has attributes color
, tail_length
, and quack
, and quack
is callable." But this is still much less strict than static languages having an interface feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With