etc./StackOverFlow

이름(문자열)을 사용하여 모듈의 함수 호출

청렴결백한 만능 재주꾼 2021. 12. 20. 10:11
반응형

질문자 :ricree


파이썬 프로그램에서 함수 이름이 있는 문자열이 주어진 함수를 호출하는 가장 좋은 방법은 무엇입니까? 예를 들어 모듈 foo 가 있고 내용이 "bar" 인 문자열이 있다고 가정해 보겠습니다. foo.bar() 를 호출하는 가장 좋은 방법은 무엇입니까?

함수의 반환 값을 eval 하므로 eval 만 사용하지 않습니다. eval 을 사용하여 해당 함수 호출의 결과를 반환하는 임시 함수를 정의하는 방법을 알아냈지만 더 우아한 방법이 있기를 바랍니다.



메소드 bar 모듈 foo 를 가정합니다.

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

2행과 3행을 다음과 같이 단축할 수 있습니다.

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

그것이 당신의 사용 사례에 더 의미가 있다면.

클래스 인스턴스 바인딩 메서드, 모듈 수준 메서드, 클래스 메서드에 대해 이러한 방식으로 getattr 을 사용할 수 있습니다. 목록은 계속됩니다.


Patrick Johnmeyer

locals()["myfunction"]()

또는

 globals()["myfunction"]()

locals 는 현재 로컬 기호 테이블이 있는 사전을 반환합니다. globals 는 전역 기호 테이블이 있는 사전을 반환합니다.


sastanin

Patrick의 솔루션이 아마도 가장 깨끗할 것입니다. 모듈도 동적으로 선택해야 하는 경우 다음과 같이 가져올 수 있습니다.

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

HS.

단순한 기여일 뿐입니다. 인스턴스화해야 하는 클래스가 동일한 파일에 있는 경우 다음과 같이 사용할 수 있습니다.

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

예를 들어:

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

그리고 클래스가 아닌 경우:

 def sampleFunc(arg): print('you called sampleFunc({})'.format(arg)) globals()['sampleFunc']('sample arg')

Sourcegeek

함수에 대한 완전한 파이썬 경로가 있는 문자열이 주어지면 다음은 해당 함수의 결과를 얻는 방법입니다.

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

ferrouswheel

Python 프로그래밍 FAQ 에 따른 가장 좋은 대답은 다음과 같습니다.

 functions = {'myfoo': foo.bar} mystring = 'myfoo' if mystring in functions: functions[mystring]()

이 기술의 주요 이점은 문자열이 함수 이름과 일치할 필요가 없다는 것입니다. 이것은 또한 케이스 구성을 에뮬레이트하는 데 사용되는 기본 기술입니다.


user3946687

그 누구도 바라지 않았던 대답 (나는 바래)

행동과 같은 평가

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

자동 가져오기를 추가하지 않는 이유

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

확인하려는 추가 사전이 있는 경우

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

우리는 더 깊이 갈 필요가 있습니다

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

00500005

그 가치를 위해 함수(또는 클래스) 이름과 앱 이름을 문자열로 전달해야 하는 경우 다음을 수행할 수 있습니다.

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

trubliphone

이 시도. 이것은 여전히 eval을 사용하지만 현재 컨텍스트에서 함수를 호출 하는 데만 사용합니다. 그런 다음 원하는대로 사용할 실제 기능이 있습니다.

이것의 주요 이점은 함수를 호출하는 시점에서 평가 관련 오류가 발생한다는 것입니다. 전화 할 때 그리고 당신은 단지 기능 관련 오류를 얻을 것이다.

 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)

tvt173

제안된 것 중 어느 것도 도움이 되지 않았습니다. 나는 이것을 발견했다.

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

나는 파이썬 2.66을 사용하고 있습니다

도움이 되었기를 바랍니다


Natdrip

이 질문 과 같이 중복으로 표시된 변수 [중복]에 메서드 이름 할당을 사용하여 클래스 내에서 메서드를 동적으로 호출하는 방법에 대해 여기에 관련 답변을 게시하고 있습니다.

시나리오는 클래스의 메서드가 동일한 클래스의 다른 메서드를 동적으로 호출하려는 것입니다. 더 넓은 시나리오와 명확성을 제공하는 원본 예제에 몇 가지 세부 정보를 추가했습니다.

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

출력(파이썬 3.7.x)

기능1: 12

기능2: 12


Serjik

getattr() 은 우아하고(약 7배 더 빠름) 메서드이지만 eval 을 사용하여 x = eval('foo.bar')() 처럼 우아한 함수(로컬, 클래스 메서드, 모듈)에서 반환 값을 얻을 수 있습니다. 그리고 일부 오류 처리를 구현하면 매우 안전합니다(getattr에 동일한 원칙을 사용할 수 있음). 모듈 가져오기 및 클래스가 있는 예:

 # import module, call module function, pass parameters and print retured value with eval(): import random bar = 'random.randint' randint = eval(bar)(0,100) print(randint) # will print random int from <0;100) # also class method returning (or not) value(s) can be used with eval: class Say: def say(something='nothing'): return something bar = 'Say.say' print(eval(bar)('nice to meet you too')) # will print 'nice to meet you'

모듈이나 클래스가 존재하지 않으면(오타 또는 더 나은 것) NameError가 발생합니다. 함수가 존재하지 않으면 AttributeError가 발생합니다. 이것은 오류를 처리하는 데 사용할 수 있습니다.

 # try/except block can be used to catch both errors try: eval('Say.talk')() # raises AttributeError because function does not exist eval('Says.say')() # raises NameError because the class does not exist # or the same with getattr: getattr(Say, 'talk')() # raises AttributeError getattr(Says, 'say')() # raises NameError except AttributeError: # do domething or just... print('Function does not exist') except NameError: # do domething or just... print('Module does not exist')

Lukas

getattr 은 개체에서 이름으로 메서드를 호출합니다. 그러나 이 객체는 호출하는 클래스의 부모여야 합니다. 부모 클래스는 super(self.__class__, self)

 class Base: def call_base(func): """This does not work""" def new_func(self, *args, **kwargs): name = func.__name__ getattr(super(self.__class__, self), name)(*args, **kwargs) return new_func def f(self, *args): print(f"BASE method invoked.") def g(self, *args): print(f"BASE method invoked.") class Inherit(Base): @Base.call_base def f(self, *args): """function body will be ignored by the decorator.""" pass @Base.call_base def g(self, *args): """function body will be ignored by the decorator.""" pass Inherit().f() # The goal is to print "BASE method invoked."

정도유

나는 이전에 문자열을 함수로 변환하는 유사한 문제에 직면하고 있습니다. 하지만 이 코드를 즉시 실행하고 싶지 않기 때문에 eval() 또는 ast.literal_eval() 사용할 수 없습니다.

"foo.bar" 라는 문자열이 있고 문자열 x 에 할당하고 싶습니다. 즉 x() ON DEMAND로 함수를 호출할 수 있습니다.

내 코드는 다음과 같습니다.

 str_to_convert = "foo.bar" exec(f"x = {str_to_convert}") x()

귀하의 질문에 대해서는 모듈 이름 foo. 다음과 같이 {} 전에:

 str_to_convert = "bar" exec(f"x = foo.{str_to_convert}") x()

경고!!! eval() 또는 exec() 는 위험한 방법이므로 안전성을 확인해야 합니다. 경고!!! eval() 또는 exec() 는 위험한 방법이므로 안전성을 확인해야 합니다. 경고!!! eval() 또는 exec() 는 위험한 방법이므로 안전성을 확인해야 합니다.


Bowen 404

__getattribute__ 메서드를 사용할 수 있습니다. 목록 메서드 이름 문자열이 있는 다음 예를 참조하세요.

 func_name = 'reverse' l = [1, 2, 3, 4] print(l) >> [1, 2, 3, 4] l.__getattribute__(func_name)() print(l) >> [4, 3, 2, 1]

Aliakbar Ahmadi

이것은 간단한 대답입니다. 예를 들어 화면을 지울 수 있습니다. 아래에는 eval 및 exec의 두 가지 예가 있습니다. 청소 후 맨 위에 0을 인쇄하거나(Windows를 사용하는 경우 clearcls 변경하고 Linux 및 Mac 사용자는 그대로 둡니다) 각각 실행합니다.

 eval("os.system(\"clear\")") exec("os.system(\"clear\")")

Number File

출처 : http:www.stackoverflow.com/questions/3061/calling-a-function-of-a-module-by-using-its-name-a-string

반응형