webentwicklung-frage-antwort-db.com.de

Python Funktionszeiger

Ich habe einen Funktionsnamen in einer Variablen wie folgt gespeichert:

myvar = 'mypackage.mymodule.myfunction'

und ich möchte meine funktion jetzt so nennen

myvar(parameter1, parameter2)

Was ist der einfachste Weg, um dies zu erreichen?

68
schneck
funcdict = {
  'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
    ....
}

funcdict[myvar](parameter1, parameter2)

Es ist viel schöner, die Funktion selbst zu speichern, 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 folgendermaßen erreichen:

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.

35
user609095
def f(a,b):
    return a+b

xx = 'f'
print eval('%s(%s,%s)'%(xx,2,3))

AUSGABE

 5
12
Pratik Deoghare

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.

8
S.Lott

Warum nicht die Funktion selbst speichern? myvar = mypackage.mymodule.myfunction ist viel sauberer.

5
ironfroggy
modname, funcname = myvar.rsplit('.', 1)
getattr(sys.modules[modname], funcname)(parameter1, parameter2)
4
Matt Anderson

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 es einen SyntaxError gibt. Dann kann ein kleiner Teil der Validierung den Ausdruck zumindest auf etwas beschränken, das in Ihrer Macht steht, z. B. das Testen, ob ein "Mypackage" gestartet wird.

2
SilverbackNet

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 registriert, um die Autorisierung für die 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 mit 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 einen Pythonic-er-Weg, um dies zu tun?

2
Rob Fagen