在不自定义编译器的情况下向Python添加新语句

noa*_*amt 5 python syntax keyword python-3.x

我想在Python中添加一个新的关键字,@ EliBendersky的精彩答案解释了如何通过更改代码和重新分发Python编译器来实现这一点.

是否可以在更改编译器代码的情况下引入新关键字?也许通过图书馆介绍它?

编辑:

例如,我想通过添加像matches这样的关键字来添加正则表达式匹配的简写:

"You can't take the sky from me" matches '.+sky.+'
Run Code Online (Sandbox Code Playgroud)

我可以使用AST转换添加新的自定义行为,但上述情况将因语法错误而失败.

Rig*_*leg 5

不改变语言就无法引入新的关键字

解析器是读取代码并决定哪些内容有意义、哪些内容无意义的工具/程序。尽管这是一个相当粗略的定义,但结果是该语言是由其解析器定义的。

ast解析器依赖于模块文档中指定的语言(形式)语法。

定义一个单纯的函数只是引入一个新特性而不修改语言,而添加一个关键字就等于引入一个新的语法,从而改变了语言的语法。

因此,从向语言添加新语法的意义上来说,添加新关键字不能在不更改语法语言的情况下进行,这需要编辑编译和执行链。

然而...

可能有一些聪明的方法来引入新功能,看起来像是新语法,但实际上只使用现有语法。例如,goto 模块依赖于该语言的一个不太为人所知的属性,即忽略限定标识符中点周围的空格。

你可以自己尝试一下:

>>> l = [1, 2, 3]
>>> l    .append(4)
>>> l
[1, 2, 3, 4]
>>> l.    append(5)
>>> l
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

这允许使用以下内容,看起来像新语法,但实际上不是:

label .myLabel
goto .myLabel
Run Code Online (Sandbox Code Playgroud)

现在,该goto模块使用解释器内部工作的方式来执行从一个goto到给定的中断label......但这是另一个问题。


我想补充一点,Python 是一种思想非常开放的语言。它提供了大量很少使用的运算符,例如@. 该运算符是从 Python 3.5 引入的,主要用于矩阵乘法,并回退到对__matmul__. 我不得不说,我从来没有在代码中见过它。那么,为什么不将它用于您的目的呢?

让我们一步一步来做。我建议定义一个r类,它将充当正则表达式。

import re

class r:
    def __init__(self, pattern):
        self.regex = re.compile(pattern)
Run Code Online (Sandbox Code Playgroud)

现在,我希望能够将@运算符与此类一起使用,以及match字符串和字符串与模式之间的 a 语义。我将定义该__matmul__方法,如下所示:

class r:
    def __matmul__(self, string):
        return bool(self.regex.match(string))
Run Code Online (Sandbox Code Playgroud)

现在,我可以执行以下操作:

>>> r("hello") @ "hello"
True
>>> r("hello"] @ "world"
False
Run Code Online (Sandbox Code Playgroud)

相当不错,但还不是那样。我还将定义该__rmatmul__方法,因此它只是退回到对__matmul__. 最后,r类看起来像这样:

class r:
    def __init__(self, pattern):
        self.regex = re.compile(pattern)

    def __matmul__(self, string):
        return bool(self.regex.match(string))

    def __rmatmul__(self, string):
        return self @ string
Run Code Online (Sandbox Code Playgroud)

现在,反向操作也可以工作:

>>> "hello" @ r("hello")
True
>>> "123456" @ r("\d+")
True
>>> "abc def" @ r("\S+$")
False
Run Code Online (Sandbox Code Playgroud)

这与您尝试的非常接近,只是我不必引入新的关键字!当然,现在r标识符必须受到保护,就像str或一样list......