0

我的目标是识别一行的方法/功能。例如,在scenario.py 中有两个函数,其中只有一行代码。我的工作是我有一个大型应用程序,我将解析该应用程序中的所有 python 文件并识别具有一行的函数。

#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 2解析Python 3代码(反之亦然),它可能会引发(并非总是如此)。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

这将忽略文档字符串并仅计算函数的主体。def与(or are )在同一行定义主体的函数lambda被认为有 0 行。

不忽略文档字符串的版本更简单一些:

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_lnotab是 a str(我认为2.6 和更高版本有__code__)和 3.x。

于 2013-10-03T13:23:45.617 回答
-1

使用检查和正则表达式:

重新进口
进口检验
导入我的模块

对于名称,inspect.getmembers(my_module, predicate=inspect.isfunction) 中的函数:
    func_source = 检查.getsource(func)
    nlines = len(re.findall('\n', func_source))
    打印(名称,行数)

于 2013-10-03T13:11:17.157 回答