Kalle en funksjon av en modul ved hjelp av sitt navn (en streng)

stemmer
1k

Hva er den beste måten å gå om å kalle en funksjon gitt en streng med funksjonen navn i et Python-program. For eksempel, la oss si at jeg har en modul foo, og jeg har en streng der innholdet er bar. Hva er den beste måten å gå om å ringe foo.bar()?

Jeg trenger å få returverdien av funksjonen, som er grunnen til at jeg ikke bare bruke eval. Jeg har funnet ut hvordan du gjør det ved hjelp av evalå definere en temp funksjon som returnerer et resultat av at funksjonskall, men jeg håper at det er en mer elegant måte å gjøre dette.

Publisert på 06/08/2008 klokken 03:36
kilden bruker
På andre språk...                            


10 svar

stemmer
1k

Antar modul foomed metode bar:

import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()

Så langt som det går, kan linjene 2 og 3 bli komprimert til:

result = getattr(foo, 'bar')()

hvis det er mer fornuftig for din bruk tilfelle. Du kan bruke getattrpå denne måten på klassen instans bundet metoder, modul-nivå metoder, klassemetoder ... listen fortsetter.

Svarte 06/08/2008 kl. 03:57
kilden bruker

stemmer
407
locals()["myfunction"]()

eller

globals()["myfunction"]()

lokalbefolkningen returnerer en ordliste med en aktuell lokal symboltabellen. globals returnerer en ordliste med global symboltabellen.

Svarte 07/05/2009 kl. 12:45
kilden bruker

stemmer
247

Patrick løsning er trolig den reneste. Hvis du trenger å dynamisk hente modulen også, kan du importere det som:

module = __import__('foo')
func = getattr(module, 'bar')
func()
Svarte 07/08/2008 kl. 11:35
kilden bruker

stemmer
81

Bare et enkelt bidrag. Hvis den klassen som vi trenger å forekomsten er i samme fil, kan vi bruke noe sånt som dette:

# Get class from globals and create an instance
m = globals()['our_class']()

# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')

# Call it
func()

For eksempel:

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('you called sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')

# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')

Og hvis ikke en klasse:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')
Svarte 19/08/2012 kl. 09:40
kilden bruker

stemmer
66

Gitt en streng, med en komplett python bane til en funksjon, dette er hvordan jeg gikk om å få resultatet av nevnte funksjon:

import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()
Svarte 16/10/2013 kl. 00:24
kilden bruker

stemmer
31

Svaret (håper jeg) ingen noensinne ønsket

Eval lignende oppførsel

getattr(locals().get("foo") or globals().get("foo"), "bar")()

Hvorfor ikke legge auto-import

getattr(
    locals().get("foo") or 
    globals().get("foo") or
    __import__("foo"), 
"bar")()

I tilfelle har vi ekstra ordbøker vi ønsker å sjekke

getattr(next((x for x in (f("foo") for f in 
                          [locals().get, globals().get, 
                           self.__dict__.get, __import__]) 
              if x)),
"bar")()

Vi trenger å gå dypere

getattr(next((x for x in (f("foo") for f in 
              ([locals().get, globals().get, self.__dict__.get] +
               [d.get for d in (list(dd.values()) for dd in 
                                [locals(),globals(),self.__dict__]
                                if isinstance(dd,dict))
                if isinstance(d,dict)] + 
               [__import__])) 
        if x)),
"bar")()
Svarte 09/04/2014 kl. 10:17
kilden bruker

stemmer
28

Det beste svaret henhold til Python programmerings FAQ vil være:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

Den primære fordelen med denne teknikken er at strengene ikke trenger å matche navnene på funksjonene. Dette er også den primære teknikk som brukes for å emulere en sak konstrukt

Svarte 24/10/2016 kl. 13:20
kilden bruker

stemmer
18

For hva det er verdt, hvis du trenger å passere funksjonen (eller klasse) navn og app navn som en streng, så kan du gjøre dette:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
Svarte 14/02/2012 kl. 05:55
kilden bruker

stemmer
15

Prøv dette. Selv om dette fremdeles bruker eval, bruker den bare det å kalle funksjonen fra den gjeldende konteksten . Deretter må du den virkelige funksjonen til å bruke som du ønsker.

Den viktigste fordelen for meg fra dette er at du vil få noen eval relaterte feil på det punktet kalle funksjonen. Da får du bare funksjonsrelaterte feil når du ringer.

def say_hello(name):
    print 'Hello {}!'.format(name)

# get the function by name
method_name = 'say_hello'
method = eval(method_name)

# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)
Svarte 07/12/2016 kl. 18:29
kilden bruker

stemmer
15

ingen av det som ble foreslått hjalp meg. Jeg gjorde oppdage dette selv.

<object>.__getattribute__(<string name>)(<params>)

Jeg bruker python 2,66

Håper dette hjelper

Svarte 28/12/2012 kl. 16:56
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more