Pythinには次の演算子は存在しません。
- ++x : 前置インクリメント
- x++ : 後置インクリメント
- --x : 前置デクリメント
- x-- : 後置デクリメント
それにも関わらず。驚いたのが次の事実
なぜか ++x --x がエラーにならないこと
前置インクリメント・前置デクリメント、
この2つがなぜかエラーが出ませんでした。
このページの目次
後置インクリメント( ++ / -- )だとエラーになるが…
いったん前置の話を置いておくとして…
例えば後置インクリメントの場合です。
▼ このようなコードを書いたとする
1 2 3 4 5 6 |
i = 0 while(i < 100): ## Print i print("i : %d" % i) ## Increment i i++ |
▼ 当然invalid syntaxエラーが出る
1 2 3 4 |
File "test.py", line 6 i++ ^ SyntaxError: invalid syntax |
インクリメント演算子がないんだから当然の話
他言語ではインクリメント(++)・デクリメント(--)がなじみ深いですが、Pythonでは一切そういった演算子はサポートされていません。
これ自体は仕方ないことです。
Pythonでは i+=1 でしかインクリメントできない
言語的に ++ -- が実装されていない。
つまり相当する処理は次でしか書けません。
▼ 面倒だけど次のように書くしかない
1 2 3 4 5 |
## iをインクリメント i += 1 ## iをデクリメント i -= 1 |
▼ 先ほどのコードを修正した結果
1 2 3 4 5 6 |
i = 0 while(i < 100): ## Print i print("i : %d" % i) ## Increment i i += 1 |
これでエラーも出ず、期待通りの結果がでます。
ところが前置の ++ / -- は一切エラーにならない !?
ところが不思議なのは前置の場合、
- 前置インクリメントはエラーが出ない
- 前置デクリメントもエラーが出ない
こういう意味不明な仕様(?)があります。
本当に理由も分からないし意図も分かりません。
※ 一応そうなる理由が判明しました。後述
▼ 意味不明な挙動を体験してみよう
1 2 3 4 5 6 |
i = 0 while(i < 100): ## Print i print("i : %d" % i) ## Increment i ++i |
▼ 実行結果。永遠に無限ループ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 i : 0 ... |
う~~~ん、どうしてなんだろう?
上記コードでは ++i というのはなんの意味も持たず、極端なこと言うならコメント文となんら変わりありません。何もしてないってことです。
もしも ++ が他に解釈の余地があるなら挙動も理解できますが、そもそもPythonでは + は加算演算子の意味しかないはず。だからやっぱり意味不明
一切エラーが出ないのが本当に不思議です。
インデントもそうだけどPythonには欠陥が多い
これは僕の持論ですが…
やっぱり「欠陥言語」呼ばわりにも理由がある
特にインデントエラーはその代表例です。
▼ Python "expected an indented block"エラーの原因
ブロックを曖昧なインデントで定義することは理解しにくい。特に他言語に慣れてるとその仕様は少し気持ち悪さを感じます。
ただそれはPythonを使えば慣れる話。
IDEのハイライト機能もあるからミスは防げます。
でも今回の前置インクリメント・デクリメントは別、
これは言語的に致命的だなと思った次第です。
詳しい理由を知ってる方は教えてください。ではまた
原因解明。どうやら ++i は +(+i) と解釈されるらしい
原因的なのが分かったので追記
釈然としないのでググってみました。
するとStackOverflowにこんな回答が
Python treats ++i as +(+i), that would compile fine, and print the same value as of i.
引用元 : https://stackoverflow.com/questions/18506579/increment-operator-i-does-not-cause-an-error-in-python
▼ この回答の日本語訳
Pythonでは ++i は +(+i) として扱われます。つまり +(+i) がコンパイルされて実行されると、それは元の i と同じ数値を表示するってことですね。
なるほど、それなら理由として筋が通ってます。
▼ 検証のために次のコードを書いてみた
1 2 3 4 5 |
i = 100 print("i : %d" % -+i) ## => i : -100 print("i : %d" % -(+i)) ## => i : -100 |
どうやらこれが ++i がエラーにならない理由
だとすると前置だけエラーになるのも納得です。
納得したけどやっぱり欠陥だと感じる……