Bellen naar een functie van een module met behulp van de naam (een tekenreeks)

stemmen
1k

Wat is de beste manier om te gaan over het aanroepen van een functie die een string met de naam van de functie in een Python-programma. Bijvoorbeeld, laten we zeggen dat ik een module foo, en ik heb een string waarvan de inhoud bar. Wat is de beste manier om te gaan roepen foo.bar()?

Ik moet de return waarde van de functie, dat is de reden waarom ik niet gewoon gebruik maken van krijgen eval. Ik bedacht hoe dit te doen door gebruik te maken evalom een tijdelijke functie die het gevolg zijn van die functie aanroep te definiëren, maar ik hoop dat er een meer elegante manier om dit te doen.

De vraag is gesteld op 06/08/2008 om 04:36
bron van user
In andere talen...                            


10 antwoorden

stemmen
1k

Aannemende module foomet methode bar:

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

Wat dat betreft, kunnen lijnen 2 en 3 worden gecomprimeerd tot:

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

als dat zinvoller voor uw use case. U kunt getattrop deze manier op de klasse-instantie gebonden methoden, module-level methoden, methoden van de klasse ... de lijst gaat maar door.

antwoordde op 06/08/2008 om 04:57
bron van user

stemmen
387
locals()["myfunction"]()

of

globals()["myfunction"]()

locals geeft een woordenboek met een huidige lokale symbol table. globals geeft een woordenboek met de wereldwijde symbool tafel.

antwoordde op 07/05/2009 om 13:45
bron van user

stemmen
229

Patrick's oplossing is waarschijnlijk de schoonste. Als u dynamisch halen de module ook, kunt u importeert het leuk:

module = __import__('foo')
func = getattr(module, 'bar')
func()
antwoordde op 07/08/2008 om 12:35
bron van user

stemmen
77

Gewoon een simpele bijdrage. Als de klasse die we nodig hebben om bijvoorbeeld in dezelfde file, kunnen we zoiets als dit te gebruiken:

# 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()

Bijvoorbeeld:

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')

En, zo niet een klasse:

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

globals()['sampleFunc']('sample arg')
antwoordde op 19/08/2012 om 10:40
bron van user

stemmen
64

Gegeven een string, met een complete python pad naar een functie, dit is hoe ik ging over het krijgen van het resultaat van de functie:

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()
antwoordde op 16/10/2013 om 01:24
bron van user

stemmen
30

Het antwoord (hoop ik) niemand ooit wilde

Eval achtig gedrag

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

Waarom niet toevoegen auto-import

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

In het geval hebben we extra woordenboeken we willen controleren

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

We moeten dieper gaan

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")()
antwoordde op 09/04/2014 om 11:17
bron van user

stemmen
26

Het beste antwoord volgens de Python programmering FAQ zou zijn:

functions = {'myfoo': foo.bar}

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

Het belangrijkste voordeel van deze techniek is dat de snaren niet nodig om de namen van de functies aan te passen. Dit is ook de voornaamste techniek om een ​​zaak construct emuleren

antwoordde op 24/10/2016 om 13:20
bron van user

stemmen
18

Voor wat het waard is, als je die nodig zijn om de functie (of klasse) de naam en app naam als een string voorbij, dan kun je dit doen:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
antwoordde op 14/02/2012 om 06:55
bron van user

stemmen
15

Probeer dit. Hoewel dit nog steeds gebruik maakt eval, gebruikt het alleen om de functie op te roepen van de huidige context . Dan heb je de echte functie te gebruiken als u wilt.

Het belangrijkste voordeel voor mij is dat je elke-eval-gerelateerde fouten op het punt van het oproepen van de functie krijgt. Dan krijg je alleen de functie gerelateerde fouten wanneer u belt.

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)
antwoordde op 07/12/2016 om 18:29
bron van user

stemmen
13

niets van wat werd voorgesteld heeft mij geholpen. Ik heb ontdek deze wel.

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

Ik gebruik python 2,66

Ik hoop dat dit helpt

antwoordde op 28/12/2012 om 17:56
bron van user

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