I would do this with a decorator. Also, storing the entity -> subclass map in a dictionary lets you replace a linear scan with a dict lookup.
class EntityBase(object):
_entity_ = None
_entities_ = {}
@classmethod
def factory(cls, entity):
try:
return cls._entities_[entity]
except KeyError:
raise FactoryError(tag, "Unknown entity")
@classmethod
def register(cls, entity):
def decorator(subclass):
cls._entities_[entity] = subclass
subclass._entity_ = entity
return subclass
return decorator
factory = EntityBase.factory
register = EntityBase.register
@register('Smith')
class Smith(EntityBase):
def __init__(self, a, b):
self.a = a
self.b = b
s = factory('Smith')(1, 2)
I'm not sure if the __entity__
attribute is actually useful to you of if you were just using it to implement the linear scan. I left it in but if you took it out, then the classes associated with entity wouldn't even need to inherit from EntityBase
and you could rename it to something like Registry
. This shallows up your inheritance tree and opens the possibility of using on classes that aren't related through common descent.
Depending on what your use case is, a better way to do it might just be
factory = {}
class Smith(object):
def __init__(self, a, b):
self.a = a
self.b = b
factory['Smith'] = Smith
class Jones(object):
def __init__(self, c, d):
self.c = c
self.d = d
factory['Jones'] = Jones
s = factory['Smith'](1, 2)
j = factory['Jones'](3, 4)
The decorator is fancier and let's us feel nice and fancy about ourselves but the dictionary is plain, useful and to the point. It is easy to understand and difficult to get wrong. Unless you really need to do something magic, then I think that that's the way to go. Why do you want to do this, anyway?