2012-11-29 6 views
9

関数が空の定義であるかどうかを検出する必要があります。 '検査' モジュールを使用してそれらを検出するための最もエレガントな方法は何Pythonで空の関数定義を検出する

foo = lambda x: None 

def foo(): 
    pass 

など:

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

などそれは次のようにすることができますか?これよりも良い方法がありますか:

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

あなたはgenerate_tokensを使用して、トークンが「DEF」または「ラムダ」で始まるかどうかを確認することができます。その後、直後に ":"と "パス"または "なし"を探します。きれいではありませんが、これはうまくいくはずです。 – spicavigo

+0

さらに別の方法は、astモジュールを使用して関数文字列を解析することです。私はあなたが詳細を考え出すことができると思います。 – spicavigo

+3

あなたのやり方は上手く見えます。 – BrenBarn

答えて

1

あなたが使っているやり方は何ですか?おそらくよりエレガントな解決策は関数のリストを持つことであり、すべての空の関数(またはすべての空でない関数)にリストに追加して関数がリストにあるかどうかをチェックする。

-2

なぜあなたはそれをしますか?それは悪いデザインのように見えます。私はあなたが何も速くしないだろうと確信しています。

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 

後者の時間に10回以上ループがあったので、呼び出しを行うよりも比較するのが遅いようです。 equals演算子は実際に確実にaを呼び出します。 コード .co_code。 eq。あなたは物事を遅くするだけです。

4

docstringを持つ空の関数のバイトコードが少し異なるため、あなたが提案するメソッドはうまくいきません。

docstringのない空の関数の値は'd\x00\x00S'ですが、docstringのある関数の値は'd\x01\x00S'です。私の目的のために

、それだけのためにテストするために、追加のケースを追加するために動作します:

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 
関連する問題