如果想要将Python代码中的函数实现全替换掉,但是保留函数定义,要怎么做?
当然,首先还是看下什么时候需要做这样的事情吧。一种情况就是,当Python代码不想对外开放,但又需要提供文档接口说明的时候。通过pydoc生成文档自然是一种选择,不过如果想配合PyCharm进行自动提示,那么还是有一份不含有具体实现的Python代码最为方便。
那如何实现呢?还是借助Python的ast
模块。在之前使用ast移除代码中的print语句里面就曾借用ast模块来移除print语句,这里也是同样的处理思路。通过ast构建抽象语法树,找到Python函数定义节点,然后移除子节点,同时保留docstring。
代码很短,直接来看吧,
class CleanFunc(NodeTransformer):
def visit_FunctionDef(self, node):
# __init__特殊处理,成员字段基本都在__init__中进行定义,因此保留函数体
if node.name == '__init__' or not node.body:
return node
# 找到docstring对应的节点,保留,移除其余子节点
child = node.body[0]
if type(child) == ast.Expr and type(child.value) == ast.Str:
node.body = [child, ast.Expr(value=ast.Pass())]
else:
node.body = [ast.Expr(value=ast.Pass())]
return node
def clean_func(input_path, output_path):
with open(output_path, 'w') as outputs:
outputs.write(astor.to_source(CleanFunc().visit(astor.parsefile(input_path))))
outputs.flush()
比如用下面这段简单的定义去运行上述清理逻辑之后,可以得到后面的输出,
输入,
class Foobar(object):
def __init__(self):
self.name = None
def get_name(self):
"""docstring"""
return self.name
输出,
class Foobar(object):
def __init__(self):
self.name = None
def get_name(self):
"""docstring"""
pass