[英]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.