想象一下有两个Python函数:
def f1(x):
return x
def f2(x):
return x,x**2
我想知道f1
返回了多少输出以及f2
返回了多少输出。
我想避免以下解决方案:
result = f1(1)
no_outputs = len(result) if type(result) == tuple else 1
由于此函数在函数返回元组时失败。
我开始使用python ast
(抽象语法树)库,并想知道是否有任何方法可以解析函数的语法树来计算返回的输出数量?
有些事情:
import inspect
import ast
src = inspect.getsourcelines(f1)[0]
string = ''.join(src)
ast_ = ast.parse(string)
我探究了ast_
,但无法找到返回的内容。
答案 0 :(得分:4)
从技术上讲,函数返回一个值。这一个值可能是元组,字典或任何任意复杂的对象(包括集合对象)。
多个返回值的出现仅仅是围绕自动解包的一些语法糖的结果,以及Python中的元组运算符实际上是(逗号; 返回中不需要括号语句,仅在(逗号)不明确的情况下才需要。
因为Python是动态类型的,所以函数可以根据其参数或程序调用时的全局状态返回不同类型的值(对象)。它可以在同一程序(解释器/ VM)会话期间为不同的调用返回不同类型的对象。
你应该考虑函数的返回类型是文档的问题......任何编写良好的Python函数都会记录它的返回类型(最好是在doc字符串中)。
对于包含某些数据结构的类的方法来说,返回 self ...这是很常见的,它允许“链式使用”模式: Foo.fiddle()。faddle()。spritz()。output() ...我们在一个简洁的表达式中对对象执行一系列操作。
答案 1 :(得分:1)
我同意评论这是一个有点奇怪的问题......但是,按照你提出的方法回答你的问题,让我们从以下简化假设开始:
只有一个return语句,它出现在最后 每项功能
逗号可用于确定“输出数量”,即
(x, 2)
和x, 2
都被认为是两个“输出”
从第2点开始,返回语句由一系列变量(可能是列表或元组)组成,并且从不会出现更复杂的表达式,如生成器或列表推导
我们假设上述情况,因为否则您几乎肯定需要正确解析有效Python代码的子集,例如通过构建AST。鉴于上述情况,您从inspect.getsourcelines()
返回的列表中获取最后一个字符串并匹配正则表达式:
In [47]: def f2(x):
....: return x, x**2
In [48]: ret2 = inspect.getsourcelines(f2)
In [49]: ret2
Out[49]: ([u'def f2(x):\n', u' return x, x**2\n'], 1)
In [55]: ret_pattern = r'return\s*(.*)\n*$'
In [56]: out2 = re.findall(ret_pattern, ret2[0][-1])
In [57]: out2
Out[57]: [u'x, x**2']
In [58]: len(out2[0].split(','))
Out[58]: 2
返回变量元组进行测试:
In [59]: def f3(x):
....: return (x, x**2, x**3)
....:
In [62]: out3 = re.findall(ret_pattern, inspect.getsourcelines(f3)[0][-1])
In [63]: len(out3[0].split(','))
Out[63]: 3