0

私の目標は、1 行のメソッド/関数を特定することです。たとえば、scenario.py には、1 行のコードしか記述されていない 2 つの関数があります。私の仕事は、私が大規模なアプリケーションを持っていることです。そのアプリケーション内のすべての python ファイルを解析し、1 行の関数を識別します。

#Scenario.py
line 1--->  class parent:
line 2--->     def father(self):
line 3--->        print "dad"
line 4--->     def mother(self):
line 5--->        print "mom"

Sample Output:

One liner function at : line=2, line =4
4

3 に答える 3

9

使用ast:

import ast

def iter_functions(code):
    tree = ast.parse(code)
    for x in tree.body:
        if isinstance(x, ast.FunctionDef):
            yield x
        elif isinstance(x, ast.ClassDef):
            for x in tree.body:
                for y in x.body:
                    yield y

code = r'''class parent:
    def father(self):
        print "dad"
    def mother(self):
        print "mom"
    def grandfather(self):
        print "grand"
        print "dad"
'''

# This is incorrect. See UPDATE
for f in iter_functions(code):
    if len(f.body) > 0 and len({stmt.lineno for stmt in f.body}) == 1:
        print(f.lineno)

版画

2
4

ノート

コードに構文エラーがある場合、このコードはSyntaxError. また、 Python 3コードをPython 2で解析しようとすると(その逆)、例外が発生する可能性がSyntaxErrorあります (常にではありません)。

アップデート

上記のforステートメントは、次のように置き換える必要があります。

for f in iter_functions(code):
    if len({node.lineno for stmt in f.body for node in ast.walk(stmt)
            if hasattr(node, 'lineno')}) == 1:
        print(f.lineno)

それ以外の場合、次の関数はワンライナーと見なされます。

def func():
    if True:
        pass
于 2013-10-03T12:01:25.463 に答える
1

「ライブ」Python 関数で動作する方法を次に示します。これは非常に CPython 固有であることに注意してください。

def func(x):
    print(x)

def numlines(func):
    lnotab = bytearray(func.__code__.co_lnotab)
    return sum(lnotab[3::2]) + (bool(lnotab) and min(lnotab[1], 1))

print(numlines(func) < 2)    # True

これは docstring を無視し、関数の本体のみをカウントします。def(または are )と同じ行で本体を定義する関数は、lambda0 行と見なされます。

docstring を無視しないバージョンはもう少し単純です:

def numlines_including_docstring(func):
    return sum(bytearray(func.__code__.co_lnotab)[1::2])

私の元のコードはひどく壊れていました。行ではなくステートメントをカウントしました。私の弁護として、私はそれを頭のてっぺんから書き留めて、 についての詳細を誤って記憶しましlnotabた.

Python 3 では への変換は必要ありませんbytearray( co_lnotabis already であるため)bytesが、そうすることでコードが Python 2.x の両方で機能するようになりますco_lnotabstr__code__

于 2013-10-03T13:23:45.617 に答える
-1

インスペクトと正規表現の使用:

再輸入
輸入検査
my_module をインポート

名前については、inspect.getmembers(my_module, predicate=inspect.isfunction) の func:
    func_source = inspect.getsource(func)
    nlines = len(re.findall('\n', func_source))
    print (名前、nlines)

于 2013-10-03T13:11:17.157 に答える