#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(‘,’)]