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.
classMusicFile:
_register = {}
def__init_subclass__(cls, **kwargs):
ifnothasattr(cls, 'extension'):
raise ValueError(cls.__name__ + ' has no extension')
MusicFile._register.update({e: cls for e in cls.extension})
@classmethoddefget_class_by_extension(cls, ext):
return cls._register.get(ext)
Example
classMP3(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:
classMusicFile(object):
known_types = {}
@staticmethoddefprocessor(ext):
return MusicFile.known_types[ext]()
deffile_types(*exts):
defregistered_class(cls):
for ext in exts: MusicFile.known_types[ext] = cls
return cls
return registered_class
@file_types('mp3')classMp3(MusicFile):
defgreet(self):
print'Hi .mp3!'@file_types('mid', 'midi')classMidi(MusicFile):
defgreet(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"