我需要将签名与Python函数的主体分开,即:
def mult(a, b):
"Multiplication"
if a or b is None:
# border case
return None
else:
return a * b
(该功能仅用于演示)。
我知道inspect.getsourcelines(mult)
将为我提供完整的代码,但我只想拥有正文,即少签名和文档字符串:
if a or b is None:
# border case
return None
else:
return a * b
是否有一种理想的方式来实现这一点,理想情况下是使用Python3内置的解析工具,而不是字符串操作?
答案 0 :(得分:2)
由于我不知道执行此操作的任何函数,因此这是一个应该起作用的自制函数。 我没有时间讨论更深入的用例。因此,我将在这里留下我不完整的答案。
def get_body(func):
""" Using the magic method __doc__, we KNOW the size of the docstring.
We then, just substract this from the total length of the function
"""
try:
lines_to_skip = len(func.__doc__.split('\n'))
except AttributeError:
lines_to_skip = 0
lines = getsourcelines(func)[0]
return ''.join( lines[lines_to_skip+1:] )
def ex_0(a, b):
""" Please !
Don't
Show
This
"""
if a or b is None:
# border case
return None
else:
return a * b
def ex_1(a, b):
''' Please !Don'tShowThis'''
if a or b is None:
# border case
return None
else:
return a * b
def ex_2(a, b):
if a or b is None:
# border case
return None
else:
return a * b
def ex_3(bullshit, hello):
pass
get_body(ex_0)
# if a or b is None:
# # border case
# return None
# else:
# return a * b
get_body(ex_1)
# if a or b is None:
# # border case
# return None
# else:
# return a * b
get_body(ex_2)
# if a or b is None:
# # border case
# return None
# else:
# return a * b
get_body(ex_3)
# pass
答案 1 :(得分:0)
如果您知道自己的代码将始终具有非空的docstring(如上),则可以使用内置的inspect库来做到这一点。
下面的代码片段应使您熟悉如何查看函数的源代码主体。
def hello_world():
"""Python port of original Fortran code"""
print("hello_world")
import inspect
source = inspect.getsource(hello_world)
doc = hello_world.__doc__
code = source.split(doc)
body = code[1]
print(body)
编辑:
我对此进行了更多考虑,您可以先删除定义行,然后删除文档字符串(如果存在)
def hello_world():
"""Python port of original Fortran code"""
print("hello_world")
import inspect
source = inspect.getsource(hello_world)
doc = hello_world.__doc__
code = source.split(':',1)
body= code[1].replace(doc, "")
body = body.replace('""""""',"")
print(body)
答案 2 :(得分:0)
您也可以使用此
i = inspect.getsource(fun_name).index('\n')
j = inspect.getsource(fun_name).rindex(':',0,i)
print(inspect.getsource(fun_name)[j+1:])
答案 3 :(得分:0)
非常感谢启发性的答案!我尝试进一步,找到了一个使用Python ast工具的解决方案。
import inspect, ast
from astunparse import unparse
def mult(a,
b): # comment
"""
This is a 'doctstring', "hello"
"""
if not a is None or b is None:
# border case
return None
else:
return a * b
def get_body(f, doc_string=False):
"""
Get the body text of a function, i.e. without the signature.
NOTE: Comments are stripped.
"""
COMMENT_START = ("'", '"')
code = inspect.getsource(mult)
# print("Function's code:\n", code)
module_tree = ast.parse(code) # this creates a module
# print("Dump:\n", ast.dump(module_tree))
# the first element of the module is evidently the function:
function_body = module_tree.body[0].body
# strip the code lines to remove the additional lines:
lines = [unparse(code_line).strip() for code_line in function_body]
# for i, line in enumerate(lines): print("%s: %s" % (i, line.strip()))
# in principle the notion of body contains the docstring:
if not doc_string:
lines = (line for line in lines if not line.startswith(COMMENT_START))
return '\n'.join(lines).strip()
s =get_body(mult)
print("---------")
print(s)
这是结果:
$ python3 function_body.py
---------
if ((not (a is None)) or (b is None)):
return None
else:
return (a * b)
您可以选择是否要使用文档字符串。这种方法的缺点(在我的用例中不应该是缺点)是删除注释。
我还留下了一些带有注释的印刷声明,以防有人想探索各个步骤。