You can copy and paste the subclass code without understanding it if you want to make abstract classes that fulfill this particular contract. We'll cover most of the unusual syntaxes in the book, but let's go over it line by line to get an overview:
@classmethod
This decorator marks the method as a class method. It essentially says that the method can be called on a class instead of an instantiated object:
def __subclasshook__(cls, C):
This defines the __subclasshook__ class method. This special method is called by the Python interpreter to answer the question: Is the class C a subclass of this class?
if cls is MediaLoader:
We check to see whether the method was called specifically on this class, rather than, say, a subclass of this class. This prevents, for example, the Wav class from being thought of as a parent class of the Ogg class:
attrs = set(dir(C))
All this line does is get the set of methods and properties that the class has, including any parent classes in its class hierarchy:
if set(cls.__abstractmethods__) <= attrs:
This line uses set notation to see whether the set of abstract methods in this class has been supplied in the candidate class. We'll cover sets in detail in the Chapter 6, Python Data Structures. Note that it doesn't check to see whether the methods have been implemented; just if they are there. Thus, it's possible for a class to be a subclass and yet still be an abstract class itself.
return True
If all the abstract methods have been supplied, then the candidate class is a subclass of this class and we return True. The method can legally return one of the three values: True, False, or NotImplemented. True and False indicate that the class is, or isn't, definitively a subclass of this class:
return NotImplemented
If any of the conditionals have not been met (that is, the class is not MediaLoader or not all abstract methods have been supplied), then return NotImplemented. This tells the Python machinery to use the default mechanism (does the candidate class explicitly extend this class?) for subclass detection.
In short, we can now define the Ogg class as a subclass of the MediaLoader class without actually extending the MediaLoader class:
>>> class Ogg(): ... ext = '.ogg' ... def play(self): ... print("this will play an ogg file") ... >>> issubclass(Ogg, MediaLoader) True >>> isinstance(Ogg(), MediaLoader) True