Python에 메서드가 있는지 확인하는 방법은 무엇입니까?


83

함수 __getattr__()에서 참조 된 변수를 찾을 수 없으면 오류가 발생합니다. 변수 또는 메서드가 개체의 일부로 존재하는지 어떻게 확인할 수 있습니까?

import string
import logging

class Dynamo:
 def __init__(self,x):
  print "In Init def"
  self.x=x
 def __repr__(self):
  print self.x
 def __str__(self):
  print self.x
 def __int__(self):
  print "In Init def"
 def __getattr__(self, key):
    print "In getattr"
    if key == 'color':
        return 'PapayaWhip'
    else:
        raise AttributeError


dyn = Dynamo('1')
print dyn.color
dyn.color = 'LemonChiffon'
print dyn.color
dyn.__int__()
dyn.mymethod() //How to check whether this exist or not

답변:


91

방법에 대한 dir()전 기능 getattr()?

>>> "mymethod" in dir(dyn)
True

7
이것은 메소드인지 변수인지 확인하지 않습니다
hek2mgl

1
dir을 사용하는 것은 좋지 않습니다-이름이 예를 들어 방법인지 확인하지 않습니다
Tony Suffolk 66

109

허락을 구하는 것보다 용서를 구하는 것이 더 쉽습니다.

메서드가 있는지 확인하지 마십시오. "검사"에 한 줄의 코드를 낭비하지 마십시오.

try:
    dyn.mymethod() # How to check whether this exists or not
    # Method exists and was used.  
except AttributeError:
    # Method does not exist; What now?

57
그러나 아마 그는 정말 그냥 ... (내 경우에서와 같이) 그 방법이 있는지 확인하기 위해, 그것을 호출하지 않습니다
플라 비우스

49
자체를 dyn.mymethod()올리면 실패 AttributeError합니다.
DK

10
@DK가 말했듯이, 이것은 검사되는 메서드에 의해 발생할 수있는 모든 AttributeError를 트랩 할 것입니다. 이것은 바람직하지 않을 수 있습니다 (이 경우 메서드의 부재를 잘못 추론 할 수 있다는 것은 말할 것도 없습니다).
ShreevatsaR

3
원칙적으로 좋으며 Python은 다른 언어와 달리 "제어 흐름으로서의 예외"문화를 가지고 있습니다. 그러나 Sentry / Raven 또는 New Relic과 같은 예외 로깅 도구를 사용하는 경우 이러한 예외를 개별적으로 필터링하거나 (가능한 경우) 노이즈를 생성해야합니다. 메서드를 호출하는 것보다 존재하는지 확인하고 싶습니다.
RichVel

2
이것은 많은 수준에서 잘못된 것입니다. 메서드 자체는 AttributeError를 일으킬 수 있으며 메서드가 존재하지 않기 때문에 감지됩니다! 또한 디버거 지원을 중단하여 예외를 중단합니다. 나는 또한 이것이 루프에 있다면 성능에 영향을 미칠 것이라고 확신합니다. 마지막으로 목록은 아니지만 메소드를 실행하고 싶지 않을 수도 있습니다. 존재하는지 확인하십시오. 이 대답을 제거하거나 최소한이 모든 경고를 넣어 순진한 사람들이 오해하지 않도록해야합니다.
Shital Shah

107

수업에 이러한 방법이 있는지 확인하십시오.

hasattr(Dynamo, key) and callable(getattr(Dynamo, key))

또는

hasattr(Dynamo, 'mymethod') and callable(getattr(Dynamo, 'mymethod'))

self.__class__대신 사용할 수 있습니다.Dynamo


23
None호출 할 수 없으므로 callable(getattr(Dynamo, 'mymethod', None)). . 내 슈퍼 () MyMethod라는 ()를 던질 수 있기 때문에 나는이 대답을 사용AttributeError
sbutler

@sbutler 그게 작동하는 것이 흥미 롭습니다. PyCharm에 따르면 getattr의 시그니처 def getattr(object, name, default=None):는 정확하지 않은 것으로 의심됩니다. 왜냐하면 만약 그렇다면 None을 세 번째 매개 변수로 전달하여 함수의 동작을 변경하지 않을 것으로 예상하기 때문입니다.
bszom

@bszom : 파이썬 셸에서 help(getattr)"기본 인수가 주어지면 속성이 존재하지 않을 때 반환됩니다. 속성이 없으면 예외가 발생합니다." -(실제로 속성이 누락 된 경우 getattr이 예외를 발생시키는 지 확인할 수 있습니다) 매우 명확하게 PyCharm이 무엇이든 잘못된 것입니다.
ShreevatsaR

@ShreevatsaR 내 의심을 확인해 주셔서 감사합니다. PyCharm은 IDE입니다.
bszom 2014 년

4
SIMPLER VERSION : 현재 클래스 INSTANCE에 속성이 있고 호출 가능한지 확인하려면 다음을 수행하십시오 if hasattr(self, "work") and callable(self.work).. 이는 인스턴스에 작업 속성 (변수 또는 함수일 수 있음)이 있는지 확인한 다음 호출 가능한지 (함수임을 의미) 확인합니다.
Mitch McMabers

14

'검사'모듈을 사용해 볼 수 있습니다.

import inspect
def is_method(obj, name):
    return hasattr(obj, name) and inspect.ismethod(getattr(obj, name))

is_method(dyn, 'mymethod')

12

나는 아래 유틸리티 기능을 사용합니다. 람다, 클래스 메서드 및 인스턴스 메서드에서 작동합니다.

유틸리티 방법

def has_method(o, name):
    return callable(getattr(o, name, None))

사용 예

테스트 클래스를 정의합시다

class MyTest:
  b = 'hello'
  f = lambda x: x

  @classmethod
  def fs():
    pass
  def fi(self):
    pass

이제 시도해 볼 수 있습니다.

>>> a = MyTest()                                                    
>>> has_method(a, 'b')                                         
False                                                          
>>> has_method(a, 'f')                                         
True                                                           
>>> has_method(a, 'fs')                                        
True                                                           
>>> has_method(a, 'fi')                                        
True                                                           
>>> has_method(a, 'not_exist')                                       
False                                                          

2
이 답변은 일반적인 접근법 ( try문장 사용 )을 사용하지 않고 멤버가 실제 기능 일 때마다 확인 하기 때문에 다른 답변보다 (적어도 제 생각에는) 더 적합 합니다. 큰 몫!
ymz

4

그것을 찾아 보는 것은 dyn.__dict__어떻습니까?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"

관례 상 underbar 접두사 메서드는 '비공개'를 의미합니다.
xtofl

double-underbar 접두사와 double-underbar 접미사는 '이것은 일반적으로 Python 인터프리터 자체에서 사용됩니다'를 의미하며 일반적으로 가장 일반적인 사용 사례에 대해 사용자 프로그램에서 동일한 효과를 얻을 수있는 방법이 있습니다 (이 경우에는 애트리뷰트에 점 표기법을 사용하는 것),하지만 유스 케이스가 정말로 그것을 요구한다면 그것을 사용하는 것은 금지되거나 잘못되지 않습니다.
deStrangis

금지되지 않습니다. 잘못은 주관적입니다. 규칙을 따르는 프로그래머를 얼마나 혼동하고 싶은지에 따라 다릅니다. 대안이없는 경우에는 사용하지 마십시오.
xtofl

3

아마도 이렇게 모든 메소드가 호출 가능하다고 가정하면

app = App(root) # some object call app 
att = dir(app) #get attr of the object att  #['doc', 'init', 'module', 'button', 'hi_there', 'say_hi']

for i in att: 
    if callable(getattr(app, i)): 
        print 'callable:', i 
    else: 
        print 'not callable:', i

1

메서드가 클래스 외부에 있고 실행하고 싶지 않고 존재하지 않는 경우 예외를 발생시키는 경우 :

'mymethod' in globals()


1
>>> def myadd (x, y) : return x + y >>> 'myadd'in globals () True
gerowam

-1

inspect패키지를 봐야한다고 생각합니다 . 그것은 당신이 물건의 일부를 '포장'할 수 있습니다. dir메소드 를 사용하면 내장 메소드, 상속 된 메소드 및 충돌을 가능하게하는 기타 모든 속성도 나열됩니다. 예 :

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    print dir(Two)

당신이에서 얻을 배열은 dir(Two)모두 포함 f_one하고 f_two물건을 내장과 많이. 다음과 같이 inspect할 수 있습니다.

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    import inspect

    def testForFunc(func_name):
        ## Only list attributes that are methods
        for name, _ in inspect.getmembers(Two, inspect.ismethod):
            if name == func_name:
                return True
        return False

    print testForFunc('f_two')

이 예제는 여전히 두 클래스의 두 메서드를 모두 나열하지만 검사를 특정 클래스에서만 작동하도록 제한하려면 약간의 작업이 필요하지만 절대적으로 가능합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.