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
9 réponses
Que diriez-vous de la fonction dir()
avant getattr()
?
>>> "mymethod" in dir(dyn)
True
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()
Que diriez-vous de le rechercher dans dyn.__dict__
?
try:
method = dyn.__dict__['mymethod']
except KeyError:
print "mymethod not in dyn"
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
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
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.
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
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?
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')
Questions connexes
Questions liées
De nouvelles questions
python
Python est un langage de programmation multi-paradigme, typé dynamiquement et polyvalent. Il est conçu pour être rapide à apprendre, comprendre, utiliser et appliquer une syntaxe propre et uniforme. Veuillez noter que Python 2 est officiellement hors support à partir du 01-01-2020. Néanmoins, pour les questions Python spécifiques à la version, ajoutez la balise [python-2.7] ou [python-3.x]. Lorsque vous utilisez une variante Python (par exemple, Jython, PyPy) ou une bibliothèque (par exemple, Pandas et NumPy), veuillez l'inclure dans les balises.