oop - Python - Getting subclass from input. Do I have to write a separate function? -
i'm working in python 2.7.8. follows slight variant of problem i'm working on.
i have large number of custom classes i've written inheritance tree. behavior encapsulated following example:
import random class animal(object): def __init__(self, name): self.name = name self.can_own_pets = false #most animals cannot own pets self.get_features() def give_pet(self, pet): if not self.can_own_pets: print(self.name+' cannot own pet!') else: self.pets.append(pet) def is_hungry(self): return random.choice([true, false]) def get_features(self): """ in classes, features function uses self.name extract features. in problem, features extracted regular expressions determined class. """ pass class human(animal): def __init__(self, name): super(human, self).__init__(name) self.can_own_pets = true self.pets = [] class dog(animal): def __init__(self, name): super(dog, self).__init__(name) def bark(self): print 'woof' def get_features(self): if 'chihuahua' in self.name: self.is_annoying = true elif 'corgi' in self.name: self.adorable = true
my program needs take in large number of animals , delegate them correct classes -- need correct attributes , methods. like modify animal constructor if name argument "finn dog" or "jake human", (the constructor) returns instance of class "dog" or "human", complete appropriate methods , attributes. now, know write function takes string , class arguments, constructs dictionary keys names of subclasses of given class, looks element of dictionary contained in string, , returns object of that class. question whether or not there way code animal class itself, seems more elegant me (as easier maintain).
here's implementation --
def _get_all_subclasses(cls): scls in cls.__subclasses__(): yield scls scls in _get_all_subclasses(scls): yield scls class animal(object): @staticmethod def from_string(s): cls in _get_all_subclasses(animal): # somehow pick class based on string... simple example... if cls.__name__ in s: return cls() raise valueerror('bummer. animal has not been discovered.') class dog(animal): pass class cat(animal): pass class lion(cat): pass print animal.from_string('is dog') print animal.from_string('is cat') print animal.from_string('lions!!!') print animal.from_string('lockness monster')
there limitations here
- all of constructors need pretty same means
cat.__init__
needs same thinghuman.__init__
does. - after create instance, code needs have logic handle
cat
,human
,dog
, etc. in cases that's ok (e.g. code cares workinganimal
), isn't (after all, cats can walk on fences, humans can't).
generally, principle live try make inputs functions permissive (is list or tuple? cares! duck typing ftw!) try have defined outputs. think makes interfaces easier use in long haul , code wrote above not pass code review if reviewer :-).
Comments
Post a Comment