简体   繁体   English

Python 检查function是否有返回语句

[英]Python Check if function has return statement

Eg例如

def f1():
    return 1

def f2():
    return None

def f3():
    print("Hello")

Functions f1() and f2() returns something but f3() not.函数f1()f2()会返回一些东西,但f3()不会。

a = f2()
b = f3()

And here a equals b so I can't just compare the result of functions to check if one has return or not.这里a等于b所以我不能只比较函数的结果来检查一个函数是否return

I like st0le's idea of inspecting the source, but you can take it a step further and parse the source into a source tree, which eliminates the possibility of false positives. 我喜欢st0le检查源代码的想法,但您可以更进一步,将源解析为源代码树,从而消除误报的可能性。

import ast
import inspect

def contains_explicit_return(f):
    return any(isinstance(node, ast.Return) for node in ast.walk(ast.parse(inspect.getsource(f))))

def f1():
    return 1

def f2():
    return None

def f3():
    print("return")

for f in (f1, f2, f3):
    print(f, contains_explicit_return(f))

Result: 结果:

<function f1 at 0x01D151E0> True
<function f2 at 0x01D15AE0> True
<function f3 at 0x0386E108> False

Of course, this only works for functions that have source code written in Python, and not all functions do. 当然,这仅适用于具有用Python编写的源代码的函数,并非所有函数都可以。 For instance, contains_explicit_return(math.sqrt) will give you a TypeError. 例如, contains_explicit_return(math.sqrt)会给你一个TypeError。

Furthermore, this won't tell you anything about whether any particular execution of a function hit a return statement or not. 此外,这不会告诉您任何特定的函数执行是否命中了return语句。 Consider the functions: 考虑功能:

def f():
    if random.choice((True, False)):
        return 1

def g():
    if False:
        return 1

contains_explicit_return will give True on both of these, despite f not encountering a return in half of its executions, and g not encountering a return ever . contains_explicit_return会给True在这两个,尽管f没有遇到在其执行的半回归, g没有遇到一回。

A function by definition always returns something. 根据定义,函数总是返回一些东西。 Even if you don't specify it, there is an implicit return None at the end of a python function. 即使你没有指定它,在python函数的末尾也有一个隐式return None

You can check for a "return" with the inspect module. 您可以使用检查模块检查“返回”。

EDIT : I just realized. 编辑 :我刚刚意识到。 This is horribly wrong because, it'll return True if there's a string literal in the function that has "return" in it. 这是非常错误的,因为如果函数中的字符串文字中包含“返回”,它将返回True。 I suppose a robust a regex will help here. 我认为一个强大的正则表达式将在这里有所帮助。

from inspect import getsourcelines


def f(n):
    return 2 * n


def g(n):
    print(n)


def does_function_have_return(func):
    lines, _  = getsourcelines(func)
    return any("return" in line for line in lines) # might give false positives, use regex for better checks


print(does_function_have_return(f))
print(does_function_have_return(g))

Inspired directly by @kevin's answer.直接受到@kevin 的回答的启发。 Some rearranging to reduce the long-line-itis and a fix for one of the issues indicated in his answer, namely nested functions.一些重新排列以减少长线问题,并修复了他的回答中指出的问题之一,即嵌套函数。

There are likely better ways to do this, I just figured an easy way is to override the behavior of ast.walk to have it skip the inner functions.可能有更好的方法来做到这一点,我只是想一个简单的方法是覆盖ast.walk的行为以让它跳过内部函数。

import ast
import inspect

def walk_special(node):
    from collections import deque
    todo = deque([node])
    top_level_node = node
    while todo:
        node = todo.popleft()

        # Added this conditional
        if isinstance(node, ast.FunctionDef):
            if node not in ast.iter_child_nodes(top_level_node):
                continue

        todo.extend(ast.iter_child_nodes(node))
        yield node

def contains_explicit_return(f):
    source = inspect.getsource(f)
    parsed = ast.parse(source)
    for node in walk_special(parsed):
        if isinstance(node, ast.Return):
            return True
    return False

def f1():
    return 1

def f2():
    return None

def f3():
    print("return")

def f4():
    def inner_a():
        return 2

    print("return")

def f5():
    def inner_b():
        return 3

    return "test"

for f in (f1, f2, f3, f4, f5):
    print(f, contains_explicit_return(f))

edit:编辑:

I realized this might not work in the case of function definitions nested inside other nodes.我意识到这对于嵌套在其他节点内的 function 定义可能不起作用。 I imagine this is unlikely to be a common occurrence so, presumably, not a big deal.我想这不太可能是普遍现象,所以大概没什么大不了的。

Example:例子:

def f6():
    if True:
        def foo():
            return 4
    print("done")

I would not have expected contains_explicit_return(f6) == False which is correct but unexpected from my current understanding.我不会期望contains_explicit_return(f6) == False这是正确的,但从我目前的理解来看是出乎意料的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM