2009-03-30 8 views
4

Wenn eine Variable entweder auf eine Funktion oder eine Klassenmethode verweist, wie kann ich herausfinden, welche es ist, und den Klassentyp erhalten, wenn es sich um eine Klassenmethode handelt, insbesondere wenn die Klasse noch wie im Beispiel deklariert wird.Wie kann man zwischen einer Funktion und einer Klassenmethode unterscheiden?

z.

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) 

Update nach den ersten beiden Antworten von David und JF Sebastian in Frage zu stellen Sie einen Punkt noch einmal betonen, die JF Sebastian angedeutet, ich möchte es unterscheiden können, wenn die Funktion in der Klasse deklariert wird (Wenn der Typ, den ich erhalte, eine Funktion und keine gebundene oder ungebundene Methode ist). dh. wo der erste Aufruf an get_info(__init__) passiert, möchte ich in der Lage sein zu erkennen, dass es eine Methode ist, die als Teil einer Klasse deklariert wird.

Diese Frage kam, da ich einen Dekorateur um es bin setzen und es wird ein Handle für die init Funktion und ich kann nicht wirklich herausfinden, ob ein Verfahren innerhalb einer Klasse oder als Stand-alone-Funktion deklariert wird

+0

Es gibt keinen Grund, warum ein Dekorator für BEIDE ungebundene Funktionen und Methodenfunktionen arbeiten sollte. Warum versuchst du das zu tun? Warum nicht zwei Dekorateure? –

Antwort

3

Um einen Punkt noch einmal betonen, die JF Sebastian erwähnt, möchte ich in der Lage sein, um es zu unterscheiden, wenn die Funktion innerhalb der Klasse deklariert wird (wenn der Typ, den ich erhalte, eine Funktion und keine gebundene oder ungebundene Methode ist). dh. wo der erste Aufruf an get_info(__init__) passiert, möchte ich in der Lage sein zu erkennen, dass es eine Methode ist, die als Teil einer Klasse deklariert wird.

Diese Frage kam, da ich einen Dekorateur um es bin setzen und es wird ein Handle für die init-Funktion, und ich kann nicht wirklich herausfinden, ob ein Verfahren innerhalb einer Klasse oder als Stand-alone-Funktion

erklärt wird

Sie können nicht. J.F. Sebastians Antwort ist immer noch 100% anwendbar. Wenn der Hauptteil der Klassendefinition ausgeführt wird, existiert die Klasse selbst noch nicht.Die Anweisungen (die __init__ Funktionsdefinition und der get_info(__init__) Aufruf) geschehen in einem neuen lokalen Namespace; Zu der Zeit, als der Aufruf an get_info auftritt, ist __init__ eine Referenz auf die Funktion in diesem Namespace, die von einer außerhalb einer Klasse definierten Funktion nicht unterscheidbar ist.

11

Sie können durch Überprüfen der Art zwischen den beiden unterscheiden:

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

oder

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

So würden Sie es in einer if Anweisung tun.

Auch können Sie die Klasse aus dem im_class Attribut des Verfahrens erhalten:

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

Es ist erwähnenswert, dass "" ist eine (etwas inkonsistent) String-Repräsentation von 'types.MethodType' Klasse (isinstance (Foo .__ init__, types.MethodType) == True). – jfs

+0

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

+0

Außerdem können Sie 'Foo .__ init__' (nicht gebundene Methode) und' Foo() .__ init__' (gebundene Methode) nicht mit 'isinstance (...) '. Sie sollten das Attribut 'im_self' ('__self__' 2.6+) überprüfen. – jfs

8

Zu der Zeit Sie get_info(__init__) (innen Klassendefinition) die __init__ ist eine ganz normale Funktion aufrufen.

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 

Ausgang (CPython, Ironpython):

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

Ausgang (Jython):

<function __init__ 1> 
<unbound method Foo.__init__> 
<method Foo.__init__ of Foo instance 2> 
<function bar 3> 
Verwandte Themen