Vra

Wat is die beste manier om te gaan oor die roeping van 'n funksie gegee 'n string met die naam van die funksie in 'n Python program. Byvoorbeeld, kom ons sê dat ek 'n module foo, en ek het 'n string waarvan die inhoud is "bar". Wat is die beste manier om foo.bar() noem?

Ek moet die terugkeer waarde van die funksie, wat is die rede waarom ek nie net gebruik eval kry. Ek uitgepluis het hoe om dit te doen deur gebruik te maak van eval om 'n tydelike funksie wat die uitslag van daardie funksie oproep terug te definieer, maar ek hoop dat daar 'n meer elegante manier om dit te doen.

Was dit nuttig?

Oplossing

Die aanvaarding module foo met metode bar:

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

Sover dit gaan, kan lyne 2 en 3 word saamgeperste om:

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

As dit maak meer sin vir jou gebruik geval. Jy kan getattr gebruik in hierdie mode op klas geval gebind metodes, module-vlak metodes, klasse metodes ... die lys gaan aan.

Ander wenke

locals()["myfunction"]()

of

globals()["myfunction"]()

locals n woordeboek met 'n huidige plaaslike simbool tafel terug. globals terug 'n woordeboek met globale simbool tafel.

Patrick se oplossing is waarskynlik die skoonste. As jy nodig het om dinamiese haal die module sowel, kan jy dit in te voer soos:

module = __import__('foo')
func = getattr(module, 'bar')
func()

Net 'n eenvoudige bydrae. As die klas wat ons nodig het om byvoorbeeld is in dieselfde lêer, kan ons so iets te gebruik:

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

Byvoorbeeld:

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, indien nie 'n klas:

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

globals()['sampleFunc']('sample arg')

Gegewe 'n string, met 'n volledige luislang pad na 'n funksie, dit is hoe ek te werk gegaan het om die uitslag van die genoemde funksie:

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

Die beste antwoord volgens die Python programmering Vrae sou wees:

functions = {'myfoo': foo.bar}

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

Die primêre voordeel van hierdie tegniek is dat die snare hoef nie die name van die funksies te pas. Dit is ook die primêre tegniek wat gebruik word om 'n saak konstruk navolg

Die antwoord (ek hoop) niemand ooit wou

Eval soos gedrag

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

Hoekom nie voeg outomaties die invoer

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

In die geval het ons ekstra woordeboeke ons wil om te kyk

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

Ons moet 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")()

Vir wat dit werd is, as jy nodig het om die funksie (of klas) naam en app naam te slaag as 'n string, dan kan jy dit doen:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)

Probeer hierdie. Terwyl dit nog steeds gebruik eval, dit gebruik dit net om dagvaar die funksie van die huidige konteks . Dan moet jy die werklike funksie te gebruik as jy wil.

Die grootste voordeel vir my uit hierdie is dat jy enige-eval verwante foute by die punt van die byeenroeping van die funksie sal kry. Dan sal jy kry net die funksie wat verband hou foute wanneer jy bel.

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)

geeneen van wat voorgestel het my gehelp. Ek het ontdek hierdie though.

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

Ek gebruik luislang 2.66

Hoop dit help

As hierdie vraag Hoe om dinamiese metodes binne 'n klas roep met behulp van metode-naam opdrag om 'n veranderlike [dubbele] gemerk as 'n dubbele as hierdie een, ek hier plaas 'n verwante antwoord:

Die scenario is, 'n metode in 'n klas wil na 'n ander metode op dieselfde klas dinamiese noem, het ek 'n paar besonderhede oorspronklike voorbeeld wat sommige wyer scenario en duidelikheid bied bygevoeg

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

Uitgawe (Python 3.7.x)

     

function1: 12

     

function2: 12

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top