Ich habe einen Funktionsnamen in einer Variablen wie dieser gespeichert:
myvar = 'mypackage.mymodule.myfunction'
und ich möchte jetzt meine Funktion so nennen
myvar(parameter1, parameter2)
Was ist der einfachste Weg, um dies zu erreichen?
Ich habe einen Funktionsnamen in einer Variablen wie dieser gespeichert:
myvar = 'mypackage.mymodule.myfunction'
und ich möchte jetzt meine Funktion so nennen
myvar(parameter1, parameter2)
Was ist der einfachste Weg, um dies zu erreichen?
Antworten:
funcdict = {
'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
....
}
funcdict[myvar](parameter1, parameter2)
Es ist viel schöner, die Funktion selbst speichern zu können, da es sich um erstklassige Objekte in Python handelt.
import mypackage
myfunc = mypackage.mymodule.myfunction
myfunc(parameter1, parameter2)
Wenn Sie das Paket jedoch dynamisch importieren müssen, können Sie dies erreichen durch:
mypackage = __import__('mypackage')
mymodule = getattr(mypackage, 'mymodule')
myfunction = getattr(mymodule, 'myfunction')
myfunction(parameter1, parameter2)
Bedenken Sie jedoch, dass all diese Arbeiten für jeden Bereich gelten, in dem Sie sich gerade befinden. Wenn Sie sie nicht irgendwie beibehalten, können Sie sich nicht darauf verlassen, dass sie in der Nähe bleiben, wenn Sie den lokalen Bereich verlassen.
def f(a,b):
return a+b
xx = 'f'
print eval('%s(%s,%s)'%(xx,2,3))
AUSGABE
5
Am einfachsten
eval(myvar)(parameter1, parameter2)
Sie haben keine Funktion "Zeiger". Sie haben eine Funktion "Name".
Während dies gut funktioniert, werden Sie eine große Anzahl von Leuten haben, die Ihnen sagen, dass es "unsicher" oder ein "Sicherheitsrisiko" ist.
Warum nicht die Funktion selbst speichern? myvar = mypackage.mymodule.myfunction
ist viel sauberer.
modname, funcname = myvar.rsplit('.', 1)
getattr(sys.modules[modname], funcname)(parameter1, parameter2)
eval(compile(myvar,'<str>','eval'))(myargs)
compile (..., 'eval') erlaubt nur eine einzige Anweisung, so dass es nach einem Aufruf keine willkürlichen Befehle geben kann oder ein SyntaxError. Dann kann ein kleines bisschen Validierung den Ausdruck zumindest auf etwas beschränken, das in Ihrer Macht steht, z. B. das Testen auf "Mypackage", um zu beginnen.
Beim Erstellen einer Bibliothek für die Authentifizierung ist ein ähnliches Problem aufgetreten. Ich möchte, dass der App-Besitzer, der meine Bibliothek verwendet, einen Rückruf bei der Bibliothek registrieren kann, um die Autorisierung für LDAP-Gruppen zu überprüfen, in denen sich die authentifizierte Person befindet. Die Konfiguration wird als config.py-Datei übergeben, die importiert wird und ein Diktat enthält alle Konfigurationsparameter.
Ich habe das zum Laufen gebracht:
>>> class MyClass(object):
... def target_func(self):
... print "made it!"
...
... def __init__(self,config):
... self.config = config
... self.config['funcname'] = getattr(self,self.config['funcname'])
... self.config['funcname']()
...
>>> instance = MyClass({'funcname':'target_func'})
made it!
Gibt es eine pythonische Möglichkeit, dies zu tun?
myvar = mypackage.mymodule.myfunction
ist viel sauberer.