Any name in your globals is accessible; this includes the create_animal()
function, and anything you may have imported.
This does means that there could be a security risk, depending on what was imported. You should, at the very least, filter the objects found on the __module__
attribute:
animal_cls = globals()[which_animal]
if animal_cls.__module__ != __name__:
raise TypeError('Not a class defined in this module!')
animal1 = animal_cls()
The alternative is to put classes that you want accessible in some kind of data structure. You could use a new dictionary:
animals = {
'Cat': Cat,
'Dog': Dog,
}
You can have each class register itself (through a decorator) into such a mapping:
animals = {}
def registered(cls):
animals[cls.__name__] = cls
return cls
@registered
class Cat():
pass
@registered
class Dog():
pass
or you could use a base class; the __subclasses__()
method then lets you list any and all derived classes:
class Animal(object):
pass
class Cat(Animal):
pass
class Dog(Animal):
pass
animals = {cls.__name__: cls for cls in Animal.__subclasses__()}