2012-11-29 8 views
9

Ich muss erkennen, ob eine Funktion eine leere Definition ist oder nicht. Es kann wie sein:Erkennen von leeren Funktionsdefinitionen in Python

def foo(): 
    pass 

oder wie:

def foo(i, *arg, **kwargs): 
    pass 

oder wie:

foo = lambda x: None 

Was ist die eleganteste Art und Weise, sie zu erkennen, indem das Modul 'inspizieren'? Gibt es einen besseren Weg als dies:

def isEmptyFunction(func): 
    e = lambda: None 
    return func.__code__.co_code == e.__code__.co_code 
+0

Sie generate_tokens verwenden können, und prüfen, ob Token mit „def“ oder „Lambda“ beginnen. Danach suchen Sie sofort nach ":" und einem "Pass" oder "None". Nicht sauber, aber ich denke, das sollte funktionieren. – spicavigo

+0

Noch ein anderer Weg wäre, ast-Modul zu verwenden und den Funktions-String zu analysieren. Ich denke, du kannst die Details ausarbeiten. – spicavigo

+3

Die Art, wie Sie es tun, sieht gut aus. – BrenBarn

Antwort

1

Die Art, wie Sie verwenden, funktioniert. Eine vielleicht "elegantere" Lösung wäre eine Liste von Funktionen, und in all Ihren leeren (oder allen nicht leeren) Funktionen würden Sie sie zur Liste hinzufügen und dann prüfen, ob die Funktion in der Liste ist oder nicht .

-2

Warum würden Sie das tun? Es sieht aus wie schlechtes Design. Ich würde wetten, dass du nichts schneller machen würdest.

python -m timeit -s'def a(): pass' -s'def b(): pass' 'if a.__code__.co_code == b.__code__.co_code: pass' 
1000000 loops, best of 3: 0.293 usec per loop 

python -m timeit -s 'def a(): pass' -s 'def b(): pass' 'a()' 
10000000 loops, best of 3: 0.0941 usec per loop 

Es scheint, wie es Größe als zu vergleichen, ist langsamer nennen nur, weil es 10 in der zweiten timeit mehr Schleifen mal waren. Der Gleichheitsoperator ist tatsächlich sicher ein. Code .co_code. äq. Du machst also die Dinge langsamer.

4

Die von Ihnen vorgeschlagene Methode funktioniert nicht ganz, da leere Funktionen mit Docstrings einen etwas anderen Bytecode haben.

Der Wert func.__code__.co_code für eine leere Funktion ohne Docstring ist 'd\x00\x00S', während der Wert für eine Funktion mit einem Docstring 'd\x01\x00S' ist.

Für meine Zwecke funktioniert es nur den zusätzlichen Fall hinzuzufügen, um zu testen:

def isEmptyFunction(func): 
    def empty_func(): 
     pass 

    def empty_func_with_doc(): 
     """Empty function with docstring.""" 
     pass 

    return func.__code__.co_code == empty_func.__code__.co_code or \ 
     func.__code__.co_code == empty_func_with_doc.__code__.co_code