◇Pythonとタブ
Pythonの特徴。見た目は同じでも動作が異なる
次のプログラムと実行結果をご覧ください。
$ cat test1.py a=1 b=1 if a==1: a += 1 if a==0: a+=1 b+=1 print(a,b) $ python test1.py (2, 1) $ cat test2.py a=1 b=1 if a==1: a += 1 if a==0: a+=1 b+=1 print(a,b) $ python test2.py (2, 2) $
どう見ても完全に同じプログラムが異なる動作をします。
「見た目ではプログラム構文が定まらない」というのがPythonの特徴で、動作は不安定なものとなります。
Python:インデントとタブの悲しい衝突
Pythonはインデント(行頭の空白文字列の長さ)が文法的意味を持つというとんでもない仕様となっています。
そのためタブが混じると完全に意味不明のものとなってしまいます。
実は先に載せたプログラムは空白を.、タブを<TT>で表すと次のようになっています。
# test1.py b=1 if.a==1: ....a.+= 1 ..<TT>..if.a==0: <TT>a+=1 b+=1 print(a,b) ⇒こう解釈される # test1.py b=1 if.a==1: ....a.+= 1 ....if.a==0: ........a+=1 ........b+=1 print(a,b) # test2.py a=1 b=1 if.a==1: ....a.+= 1 ....if.a==0: ........a+=1 ....b+=1 # space×4 print(a,b)
タブが8個の空白と解釈されているようです。
調べたところPythonによるタブの解釈には決まった約束はないようです。
タブのように個人個人のシステムによって扱いが異なるものを構文解析の基本に持ち込むなど、とんでもないことです。
Pythonは存在そのものがバグだといっても過言ではありません。(※)
タブを地球上から完全排除するかPythonを使わないか
あるいは、ブレイスを使って書いて、プリプロセッサで加工するとか
# test1.py a=1 ...b=1 if a==1 { ...<TT>...a += 1 ...if a==0 { a+=1 ...} ...b+=1} ...print(a,b) ⇒ a=1 b=1 if a==1 :#{ ...a += 1 ...if a==0 :#{ ......a+=1 ......#} ...b+=1#} print(a,b)
プリプロセッサを噛ますなら、クラスメンバ内でselfを繰り返し繰り返し繰り返し繰り返し書かなくてもよいようにしたいし、 変数名をタイプミスしたときに、新たな変数の宣言と解釈されてしまうというとんでもない仕様も何とかしたいなあ。
Python3ではエラーになることを確認(2018/01/24)
Python3ではタブとスペースの混在するインデントがエラーになることを確認しました。
$ python3 test1.py File "test1.py", line 7 b+=1 ^ TabError: inconsistent use of tabs and spaces in indentation $ python3 test2.py 2 2
まあ、愚か過ぎる仕様であったと気が付いたということですね。
とは言え、ライブラリ群のPyhton3化が進んでいない現状ではPyhtonは使えないように見えます。
※
過言(いいすぎ)かもしれません。
| 固定リンク