在Python项目中搜索递归函数

时间:2014-05-03 15:04:44

标签: python function recursion code-analysis

我需要在Python项目中找到递归的所有函数(即调用自己)。 任何想法如何处理这个?

2 个答案:

答案 0 :(得分:3)

在运行之前很难说函数是否递归。我个人会使用inspect.getclosurevars(在Python 3.3中添加):

import sys

if sys.version_info >= (3, 3, 0):
    from inspect import getclosurevars

def is_recursive(func):
    if sys.version_info >= (3, 3, 0):
        return getclosurevars(func).globals.get(func.__name__) is func
    else:
        # We can implement part of it if it's not in our standard library 
        def global_vars_in_closure(func):
            vars = {x: func.__globals__.get(x) for x in func.__code__.co_names}
            return vars

        return global_vars_in_closure(func).get(func.__name__) is func

它可以在大多数用例中正常工作,只需记住在Python 2上使用func_X而不是__X__作为函数方法。它将失败 only < / strong>如果函数包含对自身的引用而没有调用:

def false_recursive():
    false_recursive

def true_recursive():
    true_recursive()

assert is_recursive(true_recursive), 'Must not fail'
assert not is_recursive(false_recursive), 'See? It fails' # AssertionError: See? It fails

答案 1 :(得分:1)

您可以使用ast解析源代码:

code = """
def f(x):
    f(x)

def g(x):
    pass
"""

import ast

class FindRecursiveFunctions(ast.NodeVisitor):
    def __init__(self):
        self._current_func = None
        self.recursive_funcs = set()

    def generic_visit(self, node):
        if node.__class__ is ast.FunctionDef:
            self._current_func = node.name
        if node.__class__ is ast.Call and node.func.id == self._current_func:
            self.recursive_funcs.add(self._current_func)
        super(FindRecursiveFunctions, self).generic_visit(node)

>>> tree = ast.parse(code)
>>> finder = FindRecursiveFunctions()
>>> finder.visit(tree)
>>> finder.recursive_funcs
set(['f'])