Roep 'n funksie van 'n module met behulp van sy naam ( 'n string)
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.
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
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