使用AST将函数名从CamelCase更改为snake_case

时间:2017-09-18 04:20:39

标签: python function

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)

我不明白如何使用它来达到我的目的。有任何解释或其他建议吗?

1 个答案:

答案 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>