解析Python函数声明

时间:2018-04-11 16:12:32

标签: python regex

为了为我的Python代码编写自定义文档生成器,我想编写一个能够与以下内容匹配的正则表达式:

def my_function(arg1,arg2,arg3):
"""
DOC
"""

我目前的问题是,使用以下正则表达式:

def (.+)\((?:(\w+),)*(\w+)\)

我只能匹配my_functionarg2arg3(根据Pythex.org)。

我不明白我做错了什么,因为我的(?:(\w+),)*应该尽可能多地匹配参数,直到最后一个(这里arg3)。谁能解释一下?

由于

1 个答案:

答案 0 :(得分:3)

这在一般意义上是不可能的,因为Python函数不是正则表达式 - 它们可以采用无法用正则表达式语法捕获的表单,尤其是OTHER Python结构的上下文。但请记住,从你的问题中可以学到很多东西!

令人着迷的是,虽然你说你正在尝试学习正则表达式,但是你不小心偶然发现了计算机科学本身的核心,即编译理论!

我要在这篇文章中解决不到冰山一角的一小部分问题,以帮助你入门,然后提出一些免费和付费的资源来帮助你继续。

python函数本身可以采用多种形式:

def foo(x):
    "docstring"
    <body>

def foo1(x):
    """doc
    string"""
    <body>

def foo2(x):
    <body>

此外,之前的之后的功能可能不是另一个功能!

这使得使用正则表达式本身无法自动生成文档(好吧,对我来说不可能。我写的单个正则表达式不够聪明整个Python语言!)。

您需要了解的是解析(顺便说一下,我使用解析 这个术语来覆盖 parsing, tokenizing, and lexing只是为了保持简单&#34;)使用正则表达式通常是解析的一个非常重要的部分。

一般策略是将解析文件转换为语法结构。确定哪些构造是函数。隔离该功能的文本。然后,您可以使用正则表达式来解析该构造的文本。或者您可以进一步解析一个级别并将函数分解为不同的语法结构 - 函数名称,参数声明,文档字符串,正文等等......此时您的问题将得到解决。

我试图为标准函数定义编写正则表达式(没有解析),如foofoo1,但我很难做到 - 所以即使写了一些语言。

所以要明确一点,我认为解析与简单正则表达式相反的观点是你的输入跨越多行。正则表达式大多数在单行上有效。

解析函数如下所示:

def parse_fn_definition(definition):

    def parse_name(lines):
       <code>

    def parse_args(lines):
       <code>

    def parse_doc(lines):
       <code>

    def parse_body(lines):
       <code>
    ...

现在,这是真正的诀窍:这些parse函数中的每一个都返回两件事:

0)解析的正则表达式的大块 1)行的REST

所以,例如,

def parse_name(lines):
    pattern = 'def\s*?([a-zA-Z_][a-zA-Z0-9_]*?)'
    for line in lines:
        m = re.match(pattern, line)
        if m:
            res, rest = m.groups()
            return res, [rest] + lines
        else:
            raise Exception("Line cannot be parsed by parse_name: {}".format(line))

所以,一旦你分离了功能文本(那是另外一组要做的事情,通常需要创建一个名为&#34;语法的东西&#34; - 不要担心,我为你设置了下面的一些资源),你可以用以下技术解析函数文本:

def parse_fn(lines_of_text):
    name, rest = parse_name(lines_of_text)
    params, rest = parse_params(rest)
    doc_string, rest = parse_doc(rest)
    body, rest = parse_body(rest)
    function = [name, params, doc_string, body]
    res = function, rest
    return res

这个函数会返回一些代表函数的数据结构(我只是用一个简单的list来说明)和其他文本行。这将被传递给适当地编制您的function数据的内容,然后对文本的rest进行分类和处理!

无论如何,如果这是您感兴趣的事情,请不要放弃!我会提出一些不起眼的建议:

1)开始使用EASIER语言进行解析,如Scheme / LISP。这些语言的设计易于解析和操作!然后逐步使用更多不规则的语言。

2a)彼得·诺维格(Peter Norvig)已经做了一些令人惊讶且非常容易接近的工作。看看Lispy

2b)Peter Norvig的班级CS212(特别是第3单元code)非常具有挑战性,但在介绍基础语言设计概念方面表现出色。我曾经获得的每一份工作,以及我对编程的热爱都是因为这门课程。

3)如果你想进一步提升自己并且负担得起,我强烈建议你在compilersinterpreters上查看Dave Beazely的研讨会。我从Dave那里学了两门课,虽然我不能为每个人承诺这个,但我的薪水在每门课程后都翻了一倍,所以我认为这是值得的投资。

4)绝对检查计算机程序的结构和解释(向导书)和编译器(龙书)。他们会改变你的生活。

5)不要放弃!你得到了!!祝你好运!