Dans la fonction __getattr__(), si une variable référencée n'est pas trouvée, elle donne une erreur. Comment puis-je vérifier si une variable ou une méthode existe dans le cadre d'un objet?

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
69
Rajeev 28 sept. 2011 à 12:44

9 réponses

Meilleure réponse

Que diriez-vous de la fonction dir() avant getattr()?

>>> "mymethod" in dir(dyn)
True
81
Michał Šrajer 28 sept. 2011 à 08:50

Si votre méthode est en dehors d'une classe et que vous ne voulez pas l'exécuter et déclencher une exception si elle n'existe pas:

'mymethod' in globals()

1
gerowam 25 janv. 2017 à 19:55

Que diriez-vous de le rechercher dans dyn.__dict__?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"
3
deStrangis 28 sept. 2011 à 08:54

Vérifiez si la classe a une telle méthode?

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

Ou

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

Vous pouvez utiliser self.__class__ au lieu de Dynamo

95
seriyPS 28 sept. 2011 à 08:57

Peut-être comme ça, en supposant que toutes les méthodes sont appelables

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
Tonechas 7 juil. 2016 à 09:50

Je pense que vous devriez regarder le paquet inspect. Cela vous permet d'envelopper certaines choses. Lorsque vous utilisez la méthode dir, elle répertorie également les méthodes intégrées, les méthodes héritées et tous les autres attributs permettant des collisions, par exemple:

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)

Le tableau que vous obtenez de dir(Two) contient à la fois f_one et f_two et beaucoup de choses intégrées. Avec inspect, vous pouvez le faire:

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

Ces exemples répertorient toujours les deux méthodes dans les deux classes, mais si vous souhaitez limiter l'inspection pour qu'elle ne fonctionne que dans une classe spécifique, cela nécessite un peu plus de travail, mais c'est absolument possible.

-1
aweis 28 sept. 2011 à 09:52

J'utilise la fonction utilitaire ci-dessous. Il fonctionne sur lambda, les méthodes de classe ainsi que les méthodes d'instance.

Méthode utilitaire

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

Exemple d'utilisation

Définissons la classe de test

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

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

Vous pouvez maintenant essayer,

>>> 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                                                          
7
Shital Shah 11 févr. 2019 à 06:35

Il est plus facile de demander pardon que de demander la permission.

Ne vérifiez pas si une méthode existe. Ne perdez pas une seule ligne de code en "vérifiant"

try:
    dyn.mymethod() # How to check whether this exists or not
    # Method exists and was used.  
except AttributeError:
    # Method does not exist; What now?
106
John Strood 13 déc. 2018 à 08:24

Vous pouvez essayer d'utiliser le module «inspect»:

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

is_method(dyn, 'mymethod')
10
vint83 23 sept. 2014 à 23:48
7580532