이름으로 Python 메서드 호출


82

문자열에 객체와 메서드 이름이있는 경우 메서드를 어떻게 호출 할 수 있습니까?

class Foo:
    def bar1(self):
        print 1
    def bar2(self):
        print 2

def callMethod(o, name):
    ???

f = Foo()
callMethod(f, "bar1")

1
유사하지만 이것은 객체의 메서드가 아니라 모듈의 함수에 대해 묻는 이 질문 의 정확한 복제가 아닙니다 .
Grumdrig 2012

매우 밀접한 관련이 있음 (아마도 속일 수도 있음) : 해당 속성의 이름에 해당하는 문자열이 주어진 객체 속성에 액세스하는 방법 . 메서드도 속성입니다.
Aran-Fey

답변:


113

내장 getattr()기능 사용 :

class Foo:
    def bar1(self):
        print(1)
    def bar2(self):
        print(2)

def call_method(o, name):
    return getattr(o, name)()


f = Foo()
call_method(f, "bar1")  # prints 1

setattr()이름으로 클래스 속성을 설정 하는 데 사용할 수도 있습니다 .


문서에서 검색 할 내용을 찾을 수 없습니다! 감사!
Jazz

@Jazz, 그것은 내장되어 있습니다. 페이지 내 검색을 수행해야 할 수도 있습니다C-f
aaronasterling

@aaronasterling 알고 있지만 검색 할 단어를 찾을 수 없습니다!
Jazz

왜 callMethod (F, "BAR1")는 (F, "BAR1") f.callMethod 호출되지 않습니다
필립 Puthenvila

PhilipJ, Foo : 클래스 외부에서 몇 줄 앞서 정의한 메서드이기 때문입니다.
Enrico Carlesso 2013

6

비슷한 질문이 있었고 인스턴스 메서드를 참조로 호출하고 싶었습니다. 내가 찾은 재미있는 것들은 다음과 같습니다.

instance_of_foo=Foo()

method_ref=getattr(Foo, 'bar')
method_ref(instance_of_foo) # instance_of_foo becomes self

instance_method_ref=getattr(instance_of_foo, 'bar')
instance_method_ref() # instance_of_foo already bound into reference

파이썬은 놀랍습니다!


2
getattr(globals()['Foo'](), 'bar1')()
getattr(globals()['Foo'](), 'bar2')()

Foo를 먼저 인스턴스화 할 필요가 없습니다!


그것은 단지 예일뿐입니다. 저는 실제 클래스의 실제 인스턴스를 가지고 있습니다!
Jazz

2
초기화되지 않은 클래스의 메서드를 호출하면 뭔가 잘못하고 있음을 의미 할 수 있습니다.
Enrico Carlesso

foo글로벌에 없다면 어떨까요?
aaronasterling 2010-08-19

1
그렇지 않을 수도 있지만주의해야합니다 Foo. ;)
johndodo

2
def callmethod(cls, mtd_name):    
    method = getattr(cls, mtd_name)
    method()

0

다음은 Python 데코레이터를 사용하는보다 일반화 된 버전입니다. 짧거나 긴 이름으로 전화를 걸 수 있습니다. 짧고 긴 하위 명령으로 CLI를 구현할 때 유용하다는 것을 알았습니다.

파이썬 데코레이터는 훌륭합니다. Bruce Eckel (Thinking in Java)은 여기에서 Python 데코레이터를 아름답게 설명합니다.

http://www.artima.com/weblogs/viewpost.jsp?thread=240808 http://www.artima.com/weblogs/viewpost.jsp?thread=240845

#!/usr/bin/env python2

from functools import wraps


class CommandInfo(object):
    cmds = []

    def __init__(self, shortname, longname, func):
        self.shortname = shortname
        self.longname = longname
        self.func = func


class CommandDispatch(object):
    def __init__(self, shortname, longname):
        self.shortname = shortname
        self.longname = longname

    def __call__(self, func):
        print("hello from CommandDispatch's __call__")

        @wraps(func)
        def wrapped_func(wself, *args, **kwargs):
            print('hello from wrapped_func, args:{0}, kwargs: {1}'.format(args, kwargs))
            func(wself, *args, **kwargs)

        ci = CommandInfo
        ci.cmds += [ci(shortname=self.shortname, longname=self.longname, func=func)]
        return wrapped_func

    @staticmethod
    def func(name):
        print('hello from CommandDispatch.func')

        for ci in CommandInfo.cmds:
            if ci.shortname == name or ci.longname == name:
                return ci.func

        raise RuntimeError('unknown command')


@CommandDispatch(shortname='co', longname='commit')
def commit(msg):
    print('commit msg: {}'.format(msg))


commit('sample commit msg')         # Normal call by function name

cd = CommandDispatch
short_f = cd.func(name='co')        # Call by shortname
short_f('short sample commit msg')

long_f = cd.func(name='commit')     # Call by longname
long_f('long sample commit msg')


class A(object):
    @CommandDispatch(shortname='Aa', longname='classAmethoda')
    def a(self, msg):
        print('A.a called, msg: {}'.format(msg))


a = A()
short_fA = cd.func(name='Aa')
short_fA(a, 'short A.a msg')

long_fA = cd.func(name='classAmethoda')
long_fA(a, 'short A.a msg')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.