gpt4 book ai didi

python - 制作 python 的编译带文档字符串但不是断言

转载 作者:太空狗 更新时间:2023-10-30 00:15:54 24 4
gpt4 key购买 nike

Python 的 -O 开关从它编译的代码中去除断言。

Python 的 -OO 开关可以执行此操作,还可以去除文档字符串。

有什么方法可以使 Python 剥离文档字符串但断言吗?

特别是,这是否可以通过命令行或使用内置编译功能实现?

最佳答案

有点hacky,但你可以生成Abstract Syntax Trees (asts) 对于您的代码,删除任何看起来 文档字符串的内容,然后将更改后的 asts 传递给编译

给定这个模块:

$  cat func.py 
"""
This is module-level docstring.
"""

def f(x):
"""
This is a doc string
"""
# This is a comment
return 2 * x

首先,从模块源代码生成ast。

>>> import ast
>>> with open('func.py') as f:
... src = f.read()
...
>>> tree = ast.parse(src)

转储 ast 显示文档字符串存在(注释不包含在 asts 中)

>>> ast.dump(tree)
"Module(body=[Expr(value=Str(s='\\nThis is module-level docstring.\\n')), FunctionDef(name='f', args=arguments(args=[arg(arg='x', annotation=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=Str(s='\\n This is a doc string\\n ')), Return(value=BinOp(left=Num(n=2), op=Mult(), right=Name(id='x', ctx=Load())))], decorator_list=[], returns=None)])"

现在是 hacky 部分:定义一个访问者,它将访问 ast 中的每个节点,删除文档字符串。天真的实现可能只删除任何不属于赋值的字符串表达式。

>>> class Transformer(ast.NodeTransformer):
...
... def visit_Expr(self, node):
... if isinstance(node.value, ast.Str):
... return None
... return node

如果代码包含多行字符串(尽管我还没有测试过),这可能会有问题。

如果节点是一个表达式节点并且它的值是一个字符串节点(如果字符串被绑定(bind)到一个名称,那么该节点将是一个赋值节点),一个更安全的实现可能会从任何模块、函数或类定义中删除第一个节点,不是表达式)。

class Transformer(ast.NodeTransformer):

def visit_Module(self, node):
self.generic_visit(node)
return self._visit_docstring_parent(node)

def visit_FunctionDef(self, node):
self.generic_visit(node)
return self._visit_docstring_parent(node)

def visit_ClassDef(self, node):
self.generic_visit(node)
return self._visit_docstring_parent(node)

def _visit_docstring_parent(self, node):
# Common docstring removal code.
# Assumes docstrings will always be first node in
# module/class/function body.
new_body = []
for i, child_node in enumerate(node.body):
if i == 0 and isinstance(child_node, ast.Expr) and isinstance(child_node.value, ast.Str):
pass
else:
new_body.append(child_node)
node.body = new_body
return node

>>> # Transformer performs an in-place transformation.
>>> Transformer().visit(tree)

观察文档字符串不再出现在新的 ast 中:

>>> ast.dump(tree)
"Module(body=[FunctionDef(name='f', args=arguments(args=[arg(arg='x', annotation=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Return(value=BinOp(left=Num(n=2), op=Mult(), right=Name(id='x', ctx=Load())))], decorator_list=[], returns=None)])"

新的ast可以编译为代码对象并执行:

>>> ast.fix_missing_locations(new_tree)
>>> code_obj = compile(new_tree, '<string>', mode='exec')

>>> exec(code_obj, globals(), locals())
>>> globals()['f']
<function f at 0x7face8bc2158>
>>> globals()['f'](5)
10

关于python - 制作 python 的编译带文档字符串但不是断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51248540/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com