简单的 2 ++ 2 如何在Python语言的幕后工作?
如果我们在 Python解释器中输入:
>>> 2+++--2
4
>>> 2+++*2
File "<stdin>", line 1
2++*2
^
SyntaxError: invalid syntax
在这里看语法错误,我注意到它是Python设计人员设计/实现Python的方式。
据说Python是开源代码,所以我开始更多地探索它。 我使用cpython阅读了很多关于Python实现的文章。
所以这里Python编译器很容易识别这些++*%-
运算符。
因为它是用 C语言编写的。 C使用一些直接汇编代码编译器,然后转换为机器代码。
问题1: Python编译器如何识别运算符? (关于词汇和解析功能)
问题2 :我如何修改Python解释器的这种简单行为,它可以抛出语法错误,使多个运算符与多次运算符相同
>>> 2**2
4
>>> 2***2
File "<stdin>", line 1
2***2
^
SyntaxError: invalid syntax
我已阅读过cpython的这些文件:compile.c parser.c,readline.c
但是我没有遇到任何关于语法错误的异常处理机制的文件。
更新:
我仍在搜索并等待Question-2的任何答案
答案 0 :(得分:7)
你绊倒了二元和一元运算符之间的区别。在最简短的术语中,-2
实际上是数字&#34;负数2&#34;。 --2
是&#34;消极(负2)&#34;或更常规&#34;正2&#34;。 2+++--2
被解析为&#34;两个加上正面正面负面消极两个&#34;,因此归结为2+2
并为您提供4
。 +2
和-2
都是数字,但*2
不是,所以这就是您的语法错误发生的原因。
请继续阅读,如果你想要可怕的细节,但第一段最能直接回答你的问题。
你问了详细信息,所以来了。编程语言(通常是......)由称为无上下文语法的东西定义。使用Bachus Naur Form描述Python的语法。从https://docs.python.org/2/reference/expressions.html#unary-arithmetic-and-bitwise-operations开始,我们有以下定义:
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr
| m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
这定义了Python语言中的一元表达式,乘法表达式和算术表达式。在我尝试解释之前,我将把这两个都修改为与我们的问题直接相关的位:
u_expr ::= "2" | "-" u_expr | "+" u_expr
m_expr ::= u_expr | m_expr "*" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
因此,在这个语法中,u_expr
要么是2
,要么就是文字字符串+
或-
,后跟任何其他u_expr
所以以下所有内容都符合u_expr
的定义:'2', '-2', '+2', '+-2', '++++---++2'
。
m_expr
可以是u_expr
,也可以是m_expr
,然后是*
,后跟u_expr
。 2
,2*2
,2*+2
,2*++-+2
都符合此定义。
a_expr
可以是m_expr
,也可以是a_expr
,后跟加号或减号,后跟m_expr
。 2
,2*2
,2+2
,2+2*2
,2++2*-2
等。
现在让我们开始查看您的第一个语法错误2+++*2
。我们正在尝试将其转换为a_expr
。它以2+
开头,因此我们必须寻找a_expr "+" m_expr
形式的内容。 2
是a_expr
,我们已经得到了我们的文字+
,因此对于我们来说语法错误,我们必须以某种方式将++*2
转换为{{1} }}。我们可以看到每个m_expr
必须以&#34; 2&#34;开头,但是现在解析失败了。
a_expr
可以解析为2+++--2
。具体来说,a_expr
为2
,后跟文字a_expr
,后跟+
,即++--2
。
关于使m_expr
有意义的第二个问题,我担心在Python中你必须重新定义它对程序有效Python的实际意义。查看我链接的文档,您可以看到每个运算符都是明确定义的,对于2***2
我们有:
**
像Haskell这样的语言对power ::= primary ["**" u_expr]
之类的东西有着不同的理解,并且可以让你定义自己的任意运算符。在这种语言中,你可以定义一个2+2
运算符,但是Python没有这样的功能而没有引发PEP并从根本上重写Python的部分内容。
如果你想要更多的细节,那么你将会沉迷于计算机科学而不是编程 - 是的,它们是不同的。通过查找常规语言,有限状态自动机,无上下文语言和Comsky层次结构等主题开始自己开始