Шаблон регулярного выражения для поиска аргументов, переданных в функцию

#python #regex #re

Вопрос:

Для проекта я пытаюсь прочитать файл python и сохранить список всех переменных, используемых в определенной функции. Я читаю строки в файле python в строковом формате, а затем сосредотачиваюсь на строке, начинающейся с «def». Для целей этого примера представим, что у нас есть следующая строка, идентифицированная:

 def func(int_var:int,float_var=12.1,string_var=foo()):  

Я хочу использовать регулярное выражение или любой другой метод для захвата значений в этом объявлении функции.

Я хочу захватить строку "int_var:int,float_var=12.1,string_var=foo()" , а затем разделить ее на основе запятых, чтобы получить ["int_var:int","float_var=12.1","string_var=foo()"]

У меня возникли большие проблемы с тем, чтобы изолировать элементы между скобками, соответствующими «функции».

Любая помощь в создании шаблона регулярных выражений будет весьма признательна!

Комментарии:

1. Я также хотел бы захватить имя функции («func») в качестве отдельной переменной!

Ответ №1:

Вместо регулярного выражения использовать модуль намного проще и надежнее ast :

 import ast s = """ def func(int_var:int,float_var=12.1,string_var=foo()):  pass """ def form_sig(sig):  a = sig.args  d = [f'{ast.unparse(a.pop())}={ast.unparse(j)}' for j in sig.defaults[::-1]][::-1]  v_arg = [] if sig.vararg is None else [f'*{sig.vararg.arg}']  kwarg = [] if sig.vararg is None else [f'*{sig.kwark.arg}']  return [*map(ast.unparse, a), *d, *v_arg, *kwarg]  f = [{'name':i.name, 'sig':form_sig(i.args)} for i in ast.walk(ast.parse(s))   if isinstance(i, ast.FunctionDef)]   

Выход:

 [{'name': 'func', 'sig': ['int_var: int', 'float_var=12.1', 'string_var=foo()']}]  

Комментарии:

1. Спасибо, что нашли время написать это! Очень полезно.

Ответ №2:

 func_pattern = re.compile(r'^s*defs(?Plt;namegt;[A-z_][A-z0-9_] )((?Plt;argsgt;.*)):


Комментарии:

1. Я ценю это!

2. Я заметил, что это решение не работает, когда перед или после запятых есть пробелы. Например: Это работает --gt; def foo(x,y,z=foo1()) Это не удается --gt; def foo( x ,y , z=foo1()) Я пытался увидеть шаблон для идентификации аргументов, но не мог определить, как его изменить, чтобы разрешить пробелы.

3. Я не уверен, что понимаю. ". * ", найденный в шаблоне, должен соответствовать любому типу символов между круглыми скобками, включая пробелы. Быстрая проверка с моей стороны показывает, что шаблон совпадает с обоими приведенными вами примерами (после добавления двоеточия в конец строки, не заканчивающиеся двоеточием, не будут соответствовать шаблону, который я дал). Возможно, проблема в том, что нам не нужны пробелы в выходных данных? Если вы хотите удалить пробелы, которые появляются вокруг аргументов после получения совпадения, вы можете сделать: func_args = [arg.strip() для arg в match.group('args'),split(',')]

) match = func_pattern.match('def my_func(arg1, arg2):') func_name = match.group('name') # my_func func_args = match.group('args').split(',') # ['arg1', 'arg2']

Комментарии:

1. Я ценю это!

2. Я заметил, что это решение не работает, когда перед или после запятых есть пробелы. Например: Это работает —gt; def foo(x,y,z=foo1()) Это не удается —gt; def foo( x ,y , z=foo1()) Я пытался увидеть шаблон для идентификации аргументов, но не мог определить, как его изменить, чтобы разрешить пробелы.

3. Я не уверен, что понимаю. «. * «, найденный в шаблоне, должен соответствовать любому типу символов между круглыми скобками, включая пробелы. Быстрая проверка с моей стороны показывает, что шаблон совпадает с обоими приведенными вами примерами (после добавления двоеточия в конец строки, не заканчивающиеся двоеточием, не будут соответствовать шаблону, который я дал). Возможно, проблема в том, что нам не нужны пробелы в выходных данных? Если вы хотите удалить пробелы, которые появляются вокруг аргументов после получения совпадения, вы можете сделать: func_args = [arg.strip() для arg в match.group(‘args’),split(‘,’)]