2010-01-18 4 views
0

Je veux savoir si une fonction est définie pour une instance d'une classeComment savoir si une fonction est définie pour une instance d'une classe en Python?

class c(object): 
    def func(self): pass 
cc = c() 

>>> is_function_defined_for_instance(cc,'func') 
True 
>>> is_function_defined_for_instance(cc,'cnuf') 
False 

mes propres tentatives de la fonction est:

def is_function_defined_for_instance(instance,function): 
    return callable(getattr(instance,function,None)) 

# returns True iff function is defined for class of instance (not super classes) 
def is_function_defined_for_instance(instance,function): 
    return bool(instance.__class__.__dict__.get(function)) 

est-il un ou intégré d'une manière plus agréable de accomplir ce que je cherche?

Répondre

2
>>> def is_func(instance, func): 
    test = getattr(instance, func, None) 
    if test and hasattr(test, '__call__'): 
     return True 

>>> is_func('', 'len') 
>>> is_func({}, 'fromkeys') 
True 

ou vous pourriez utiliser le module inspect:

>>> import inspect 
>>> test = getattr(cc, 'func', None) 
>>> inspect.ismethod(test) 
True 
+0

quelle est la différence entre callable (fonction) et hasattr (fonction, '__ call__')? –

+1

'callable' n'existe pas dans py3k – SilentGhost

0

Pouvez-vous jeter une sorte d'exception personnalisée si la méthode est manquante? (Je viens de la terre Ruby ici :))

+0

en fait, c'est probablement la bonne façon de faire les choses la plupart du temps (plus facile de demander pardon) – cobbal

3

En Python 2.6 ou mieux, l'approche préconisée est:

import collections 

def is_func(instance, func): 
    return isinstance(getattr(instance, func, None), collections.Callable) 

Les nouvelles ABC (classes de base abstraites) dans le module collections sont la façon correcte, en Python 2.6+ et 3.any, d'effectuer ce genre de "vérifications de type de type canard" - beaucoup plus élégant, unform, et F Plus résistant que les anciennes approches telles que callable intégré, operator.isCallable, ou en vérifiant la présence de méthodes spéciales spécifiques telles que __call__. Puisque isinstance peut maintenant être surchargé, laissez-le à l'ABC pour le surcharger et effectuer les vérifications en encapsulant toutes les approches de niveau inférieur qui fonctionnent le mieux! L'élégance et les avantages de la nouvelle approche sont tels que, si vous avez besoin de rendre votre code portable entre des versions plus anciennes et plus récentes de Python, je recommande d'encapsuler les "tests de dactylographie" dont vous avez besoin dans un module qui peut définir sa fonction en fonction du sys.version - en utilisant isinstance(x, collections.Y) en 2.6 ou mieux, et des approches plus anciennes telles que hasattr(x, '__somespecialmethod__') ou callable(x) en 2.5 ou pire.

Plus important encore, et plus généralement, ne pas pollue votre nouveau code d'application ligne principale avec les anciens, les moyens inférieurs - si les exigences de rétro-portabilité forcer votre système dans son ensemble d'avoir une « ordures » (pour continuez à fonctionner sur les vieilles versions de Python), au moins cachez-la décemment dans son propre "compartiment" (où un jour vous pourrez facilement l'emporter si les contraintes de déploiement de votre application le permettent!).

Questions connexes