2013-03-20 73 views
0

我正在使用Python 2.7。Python解釋器行爲?

事情是這樣的:

>>> 2+++2 
4 

我不知道是Python解釋器如何解釋這種表達。

我能想出的唯一原因是第一個「+」之後的連續「+」被認爲是一元運算符,第一個「+」被認爲是二元運算符,但實際上是什麼機制我不確定。

我想讓某人用Python編程語言的語法細節來回答這個問題,並且還會報告一些其他含糊不清的表達式。我想出了下面列出的一些其他表達式(及其結果):

>>> 2------------2 
4 
>>> 2+-2+-2+-2+-2+-2-------------------------2 
-10 
+3

這些都不明確(只有毫無意義),也沒有提出有關您正面臨的真正編程問題的問題。 – geoffspear 2013-03-20 11:16:08

+1

此外,要求更模糊的表達式使得這個問題不具有建設性。 – 2013-03-20 11:16:52

回答

7

你是對的;正如你所期望的那樣,Python將其解釋爲2 + (++2)。您可以通過查看2 + 2和2 +++ 2編譯字節碼看到這一點,如下所示:

>>> dis.dis(lambda: 2+2) 
    1   0 LOAD_CONST    2 (4) 
       3 RETURN_VALUE   
>>> dis.dis(lambda: 2+++2) 
    1   0 LOAD_CONST    1 (2) 
       3 LOAD_CONST    1 (2) 
       6 UNARY_POSITIVE  
       7 UNARY_POSITIVE  
       8 BINARY_ADD   
       9 RETURN_VALUE  

你可能想知道爲什麼Python解析2 +++ 2這樣。首先,代碼被分解成記號:

>>> from cStringIO import StringIO 
>>> import tokenize 
>>> tokenize.generate_tokens(StringIO("2+++2").readline) 
    9 <generator object generate_tokens at 0x0000000007BC7480> 
>>> list(tokenize.generate_tokens(StringIO("2+++2").readline)) 
    10 
[(2, '2', (1, 0), (1, 1), '2+++2'), 
(51, '+', (1, 1), (1, 2), '2+++2'), 
(51, '+', (1, 2), (1, 3), '2+++2'), 
(51, '+', (1, 3), (1, 4), '2+++2'), 
(2, '2', (1, 4), (1, 5), '2+++2'), 
(0, '', (2, 0), (2, 0), '')] 

它的解析器,然後憑證清單關聯成語法樹:

>>> st = ast.parse("2+++2") 
>>> st 
    36 <_ast.Module at 0x7d2acc0> 
>>> ast.dump(st) 
    37 'Module(body=[Expr(value=BinOp(left=Num(n=2), op=Add(), right=UnaryOp(op=UAdd(), operand=UnaryOp(op=UAdd(), operand=Num(n=2)))))])' 

這是繼標準消歧規則。

2

看看Python定義unarybinary算術運算的方式。特別是一元表達式:

u_expr ::= power | "-" u_expr | "+" 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 

這幾乎意味着,當你有一個二進制表達式,你看第一個原子,然後符號,並讀取下一個二進制/一元表達。其內容如下代碼:

2+-2+-2+-2+-2+---2+-2 

實質類似:

2 + (-2) + (-2) + (-2) + (-2) + (-(-(-2))) + (-2) 
1

這是完全平原grammar

arith_expr: term (('+'|'-') term)* 
term: factor (('*'|'/'|'%'|'//') factor)* 
factor: ('+'|'-'|'~') factor | power 

所以因爲任何因素可以由一元的運營商之一的前面,這將延長到算術表達式消耗二元運算符。這並不含糊,因爲我們既沒有C的++運算符,也沒有Haskell定義新運算符的能力。