Metaclass Vs Inheritance For Predefined Class Creation
Solution 1:
This answer only applies for Python 3.6+. If you have the option to upgrade to the most recent Python version, there are numerous reasons why you should and the following may be one of them.
Python 3.6 introduced the __init_subclass__ hook that is exectued after a class is subclassed.
class MusicFile:
_register = {}
def __init_subclass__(cls, **kwargs):
if not hasattr(cls, 'extension'):
raise ValueError(cls.__name__ + ' has no extension')
MusicFile._register.update({e: cls for e in cls.extension})
@classmethod
def get_class_by_extension(cls, ext):
return cls._register.get(ext)
Example
class MP3(MusicFile):
extension = ['mp3']
class MIDI(MusicFile):
extension = ['midi']
MusicFile.get_class_by_extension('mp3') # <class '__main__.MP3'>
MusicFile.get_class_by_extension('midi') # <class '__main__.MIDI'>
Note that this is very similar to the factory approach suggested by bipll, but in a more straightforward and maintainable way.
Solution 2:
I want to be able to maybe have all the subclasses of MusicFile registered to be able to instantiate the right one (given a file path, for example).
So you probably want to implement a Factory?
This factory can probably be auto-built with metaclasses. One serious issue I see is using class's own extension member to register it, so to me, it is easier done with metaclasses' eternal competition, decorators:
class MusicFile(object):
known_types = {}
@staticmethod
def processor(ext):
return MusicFile.known_types[ext]()
def file_types(*exts):
def registered_class(cls):
for ext in exts: MusicFile.known_types[ext] = cls
return cls
return registered_class
@file_types('mp3')
class Mp3(MusicFile):
def greet(self):
print 'Hi .mp3!'
@file_types('mid', 'midi')
class Midi(MusicFile):
def greet(self):
print 'Hi, Music Instruments Digital Interface!'
pcsor = MusicFile.processor('mp3')
pcsor.greet() # Hi .mp3!
pcsor = MusicFile.processor('mid')
pcsor.greet() # Hi, Music Instruments Digital Interface!
pcsor = MusicFile.processor('midi')
pcsor.greet() # Hi, Music Instruments Digital Interface!
pcsor = MusicFile.processor('s3m') # KeyError: 's3m'
pcsor.greet()
Post a Comment for "Metaclass Vs Inheritance For Predefined Class Creation"