Here在这个问题中,我想要一种方法将函数名从CamelCase转换为snake_case,这是使用AST建议的评论之一。 我找到了一个代码片段来查找脚本中的所有函数调用
import ast
from collections import deque
class FuncCallVisitor(ast.NodeVisitor):
def __init__(self):
self._name = deque()
@property
def name(self):
return '.'.join(self._name)
@name.deleter
def name(self):
self._name.clear()
def visit_Name(self, node):
self._name.appendleft(node.id)
def visit_Attribute(self, node):
try:
self._name.appendleft(node.attr)
self._name.appendleft(node.value.id)
except AttributeError:
self.generic_visit(node)
def get_func_calls(tree):
func_calls = []
for node in ast.walk(tree):
if isinstance(node, ast.Call):
callvisitor = FuncCallVisitor()
callvisitor.visit(node.func)
func_calls.append(callvisitor.name)
return func_calls
if __name__ == '__main__':
tree = ast.parse(open("some_dir").read())
print(get_func_calls(tree))
使用这段代码我在我的脚本中有所有函数调用,现在我想编写一个将这个名称转换为snake_case的代码。 我发现这段代码片段用于修改AST树中的节点
class RewriteName(ast.NodeTransformer):
def visit_Name(self, node):
return ast.copy_location(ast.Subscript(
value=ast.Name(id='data', ctx=ast.Load()),
slice=ast.Index(value=ast.Str(s=node.id)),
ctx=node.ctx
), node)
tree = RewriteName().visit(tree)
我不明白如何使用它来达到我的目的。有任何解释或其他建议吗?
答案 0 :(得分:0)
我有点迟了,但也许将来会发现。
无论如何,这是一个快速的技巧。实际上,您的解决方案几乎就在那里。 name
方法返回您的名称,然后您可以随意更改它。因此,在您的def get_func_calls(tree)
调用中,您可以操纵字符串并将新名称重新分配给Call
对象。
ccName = callvisitor.name # work with some local var
new_name = '' # the new func name
for char_i in range(len(ccName)): # go over the name
if ccName[char_i].isupper(): # check if the current char is with uppercase
if ccName[char_i - 1] == '.': # check if the previous character is a dot
new_name += ccName[char_i].lower() # if it is, make the char to lowercase
else:
new_name += '_' + ccName[char_i].lower() # otherwise add the snake_
else:
new_name += ccName[char_i] # just add the rest of the lower chars
callvisitor._name = new_name # just re-asign the new name
func_calls.append(callvisitor._name)
这绝对不是一个很好的解决方案,它还取决于您是否只想更改函数定义或文件中的每个单个函数调用,但这应该使您对如何更改ast
有所了解。 / p>