我想在Python中创建一个与Python源代码中的一行匹配的正则表达式,并返回一个函数调用列表。
典型的线条如下所示:
something = a.b.method(time.time(), var=1) + q.y(x.m())
,结果应为:
["a.b.method()", "time.time()", "q.y()", "x.m()"]
我有两个问题:
谢谢你的帮助
答案 0 :(得分:11)
我不认为正则表达式是最好的方法。请考虑使用ast module,例如:
class ParseCall(ast.NodeVisitor):
def __init__(self):
self.ls = []
def visit_Attribute(self, node):
ast.NodeVisitor.generic_visit(self, node)
self.ls.append(node.attr)
def visit_Name(self, node):
self.ls.append(node.id)
class FindFuncs(ast.NodeVisitor):
def visit_Call(self, node):
p = ParseCall()
p.visit(node.func)
print ".".join(p.ls)
ast.NodeVisitor.generic_visit(self, node)
code = 'something = a.b.method(foo() + xtime.time(), var=1) + q.y(x.m())'
tree = ast.parse(code)
FindFuncs().visit(tree)
结果
a.b.method
foo
xtime.time
q.y
x.m
答案 1 :(得分:4)
$ python3
>>> import re
>>> from itertools import chain
>>> def fun(s, r):
... t = re.sub(r'\([^()]+\)', '()', s)
... m = re.findall(r'[\w.]+\(\)', t)
... t = re.sub(r'[\w.]+\(\)', '', t)
... if m==r:
... return
... for i in chain(m, fun(t, m)):
... yield i
...
>>> list(fun('something = a.b.method(time.time(), var=1) + q.y(x.m())', []))
['time.time()', 'x.m()', 'a.b.method()', 'q.y()']
答案 2 :(得分:2)
/([.a-zA-Z]+)\(/g
应与方法名称匹配;因为你有一些嵌套,你必须添加parens。
答案 3 :(得分:1)
我真的不懂Python,但我可以想象,正确使用这项工作会带来一些复杂性,例如:
但是对于你的例子,这样的表达式有效:
(?:\w+\.)+\w+\(
答案 4 :(得分:0)
我有一个例子证明这在Python3中是可行的
强>
import re def parse_func_with_params(inp): func_params_limiter = "," func_current_param = func_params_adder = "\s*([a-z-A-Z]+)\s*" try: func_name = "([a-z-A-Z]+)\s*" p = re.compile(func_name + "\(" + func_current_param + "\)") print(p.match(inp).groups()) except: while 1: func_current_param += func_params_limiter + func_params_adder try: func_name = "([a-z-A-Z]+)\s*" p = re.compile(func_name + "\(" + func_current_param + "\)") print(p.match(inp).groups()) break except: pass
命令行输入:animalFunc(lion,tiger,giraffe,singe)
输出:('animalFunc','lion','tiger','giraffe','singe')
如您所见,函数名称始终是列表中的第一个,其余的是传递的参数名称