Pregunta

I am using globals() to create instances of classes on the fly.

For eg.

animals.py

class Cat():
    pass

class Dog():
    pass

test.py

#import animals

def create_animal():
    # Take 'which_animal' input from 
    # somewhere in form of string
    try:
    animal1 = globals()[which_animal]()
    catch:
    .
    .

I did this to avoid long if-else ladder.
What are pros and cons of this method ?
Is there any alternative method for the same ?
Is it creating security threat ?

¿Fue útil?

Solución

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__()}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top