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 02:36
bron van user
In andere talen...                            


12 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 02:57
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 10:35
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 11:45
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 03:55
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 08:40
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 14:56
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 15/10/2013 om 23: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 09: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 12:20
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 16:29
bron van user

stemmen
0

Aangezien deze vraag Hoe dynamisch methoden die in een klasse te bellen met behulp van methode-naam opdracht aan een variabele [dubbele] gemarkeerd als een duplicaat als deze, ik ben hier het plaatsen van een gerelateerd antwoord:

Het scenario is, een methode in een klasse wilt naar een andere methode op dezelfde klasse dynamisch te noemen, heb ik enkele details naar het originele voorbeeld dat wat breder scenario en helderheid biedt toegevoegd:

class MyClass:
def __init__(self, i):
    self.i = i

def get(self):
    func = getattr(MyClass, 'function{}'.format(self.i))
    func(self, 12)   # This one will work
    # self.func(12)    # But this does NOT work.


def function1(self, p1):
    print('function1: {}'.format(p1))
    # do other stuff

def function2(self, p1):
    print('function2: {}'.format(p1))
    # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

Output (Python 3.7.x)

functie1: 12

function2: 12

antwoordde op 26/03/2019 om 16:15
bron van user

stemmen
0

Dit is een eenvoudig antwoord, dit zal u toelaten om het scherm te wissen bijvoorbeeld. Er zijn twee voorbeelden hieronder, met eval en exec, die wordt afgedrukt 0 aan de top na het schoonmaken (als u Windows gebruikt, veranderen clearnaar clsrespectievelijk, Linux en Mac-gebruikers laten zoals is bijvoorbeeld) of gewoon voer het uit,.

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")
antwoordde op 28/08/2019 om 18:46
bron van user

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