Как проверить, существует ли метод в Python? - PullRequest
59 голосов
/ 28 сентября 2011

В функции __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

Ответы [ 9 ]

100 голосов
/ 28 сентября 2011

Проще просить прощения, чем спрашивать разрешения.

Не проверяйте, существует ли метод.Не тратьте ни одной строки кода на «проверку»

try:
    dyn.mymethod() # How to check whether this exists or not
    # Method exists and was used.  
except AttributeError:
    # Method does not exist; What now?
88 голосов
/ 28 сентября 2011

Проверить, есть ли у класса такой метод?

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

или

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

Вы можете использовать self.__class__ вместо Dynamo

76 голосов
/ 28 сентября 2011

Как насчет dir() функции до getattr()?

>>> "mymethod" in dir(dyn)
True
8 голосов
/ 24 сентября 2014

Вы можете попробовать использовать модуль 'inspect':

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

is_method(dyn, 'mymethod')
3 голосов
/ 07 июля 2016

Может быть так, при условии, что все методы могут быть вызваны

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
3 голосов
/ 28 сентября 2011

Как насчет поиска в dyn.__dict__?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"
1 голос
/ 11 февраля 2019

Я использую ниже функцию полезности.Он работает с лямбдами, методами классов и методами экземпляров.

Метод утилит

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                                                          
1 голос
/ 25 января 2017

Если ваш метод находится вне класса, и вы не хотите запускать его и вызывать исключение, если он не существует:

'mymethod' in globals()

0 голосов
/ 28 сентября 2011

Думаю, вам стоит взглянуть на пакет 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')

В этих примерах все еще перечисляются оба метода в двух классах, но если вы хотите ограничить проверку только функциями в определенном классе, это требует немного больше работы,но это абсолютно возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...