2009-03-30 5 views
4

Si une variable fait référence à une méthode ou à une méthode de classe, comment puis-je savoir de quel type il s'agit et obtenir le type de classe s'il s'agit d'une méthode de classe, notamment lorsque la classe est déclarée comme dans l'exemple donné.Comment faire la distinction entre une fonction et une méthode de classe?

par ex.

def get_info(function_or_method): 
    print function_or_method 

class Foo(object): 
    def __init__(self): 
     pass 

    get_info(__init__) 

def bar(): 
    pass 

get_info(bar) 

Mise à jour à la question après les deux premières réponses de David et JF Sebastian Pour souligner encore une fois un point JF Sebastian a fait allusion, je veux être en mesure de distinguer lorsque la fonction est déclarée dans la classe (lorsque le type que j'obtiens est une fonction et non une méthode liée ou non liée). c'est à dire. où le premier appel à get_info(__init__) se produit, j'aimerais pouvoir détecter que c'est une méthode déclarée comme faisant partie d'une classe. Cette question a été soulevée depuis que je mets un décorateur autour de la fonction init et je n'arrive pas à savoir si une méthode est déclarée dans une classe ou une fonction autonome

+0

Il n'y a aucune raison qu'un décorateur travaille pour les fonctions non liées et les fonctions de méthode. Pourquoi essayez-vous de faire cela? Pourquoi ne pas avoir deux décorateurs? –

Répondre

3

Pour souligner encore une fois un point JF Sebastian a fait allusion, je veux être en mesure pour le distinguer quand la fonction est déclarée dans la classe (quand le type que j'obtiens est une fonction et non une méthode liée ou non liée). c'est à dire. où le premier appel à get_info(__init__) se produit, j'aimerais pouvoir détecter que c'est une méthode déclarée comme faisant partie d'une classe.

Cette question a été soulevée depuis que je suis en train un décorateur autour d'elle et il obtient une poignée à la fonction init et je ne peux pas vraiment si une méthode est déclarée dans une classe ou en fonction autonome

Vous ne pouvez pas. La réponse de J.F. Sebastian est toujours 100% applicable. Lorsque le corps de la définition de classe est en cours d'exécution, la classe elle-même n'existe pas encore.Les instructions (la définition de la fonction __init__ et l'appel get_info(__init__)) se produisent dans un nouvel espace de noms local; au moment où l'appel à get_info se produit, __init__ est une référence à la fonction dans cet espace de noms, qui est impossible à distinguer d'une fonction définie en dehors d'une classe.

11

Vous pouvez distinguer entre les deux en vérifiant le type:

>>> type(bar) 
<type 'function'> 
>>> type(Foo.__init__) 
<type 'instancemethod'> 

ou

>>> import types 
>>> isinstance(bar, types.FunctionType) 
True 
>>> isinstance(bar, types.UnboundMethodType) 
True 

ce qui est la façon dont vous le feriez dans une instruction if.

En outre, vous pouvez obtenir la classe de l'attribut im_class de la méthode:

>>> Foo.__init__.im_class 
__main__.Foo 
+0

Il est à noter que "" est une représentation (quelque peu incohérente) de la classe 'types.MethodType' (isinstance (Foo .__ init__, types.MethodType) == True). – jfs

+0

btw, isinstance (bar, types.UnboundMethodType) est False – jfs

+0

En outre, vous ne pouvez pas distinguer 'Foo .__ init__' (méthode non liée) et' Foo() .__ init__' (méthode liée) en utilisant 'isinstance (...) '. Vous devriez vérifier l'attribut 'im_self' (' __self__' 2.6+). – jfs

8

Au moment où vous appelez get_info(__init__) (dans la définition de classe) la __init__ est une fonction ordinaire.

def get_info(function_or_method): 
    print function_or_method 

class Foo(object): 
    def __init__(self): 
     pass 
    get_info(__init__) # function 

def bar(): 
    pass 

get_info(Foo.__init__) # unbound method 
get_info(Foo().__init__) # bound method 
get_info(bar)   # function 

sortie (CPython, IronPython):

<function __init__ at ...> 
<unbound method Foo.__init__> 
<bound method Foo.__init__ of <__main__.Foo object at ...>> 
<function bar at ...> 

sortie (Jython):

<function __init__ 1> 
<unbound method Foo.__init__> 
<method Foo.__init__ of Foo instance 2> 
<function bar 3> 
Questions connexes