【ワレコのPython】インデント位置で文脈が変わるのは設計ミスだと思う

スポンサーリンク

このところ、Pythonとやらを使って極秘のプログラム開発を行っている。

このプログラム開発の過程でPythonの長所、短所を発見した。

自称、プログラミング言語評論家のワテであるが、そのPythonが持つ短所(あるいは欠点と言っても良い)に関する感想を述べてみたい。

かつ、そのPython特有の欠点を解決する為の画期的なアイディアを思い付いた。

そのアイディアが世間に普及すればPython業界に革命が起きる事は間違い無い。

当記事ではそれらを紹介したい。

ちなみに、ワテの開発環境は以下の通り。

  • 自作Windows10x64パソコン(詳細)
  • Visual Studio 2017 Community 15.8.1

だ。

 

では、本題に入ろう。

スポンサーリンク
ワテ推薦のプログラミングスクールで学ぶ
スポンサーリンク
スポンサーリンク

Pythonにはカッコ {・・・} が無いぞ

Pythonにはカッコ {・・・} が登場しないと言うのは、ワテも知っていた。

例えば、C,C++,C#系の言語でループ処理をするならこんな感じか。

for (int i = 0; i < 3; i++) {
	printf("%d\n", i);
}

その実行結果は、

0
1
2

 

Pythonの場合ならこんな感じだ。

for i in range(3):
    print(i)

その実行結果は、

0
1
2

となり、先ほどのC言語の場合と同じ結果になる。

まあ、これくらい単純なコードならカッコ{・・・} が無くても困らないのだが、実際のプログラミングの状況では、カッコの無いPythonの文法には、ワテは戸惑う事が多い。

それを紹介しよう。

C言語やPythonで2重ループの例

では、C言語でforループが入れ子になった二重ループの場合はこんな感じになる。

for (int i = 0; i < 3; i++) {
	printf("i=%d\n", i);
	for (int j = 0; j < 3; j++) {
		printf("\tj=%d\n", j);
	}
}

その実行結果は以下の通り。

i=0
        j=0
        j=1
        j=2
i=1
        j=0
        j=1
        j=2
i=2
        j=0
        j=1
        j=2

 

これをPythonで書くとこんな感じか。

for i in range(3):
    print('i=',i)
   
    for j in range(3):
        print('\tj=',j)

その実行結果は、C言語の場合と同じで以下の通り。

i= 0
        j= 0
        j= 1
        j= 2
i= 1
        j= 0
        j= 1
        j= 2
i= 2
        j= 0
        j= 1
        j= 2

ここまでは問題は無い。

Pythonはインデントの位置が文脈に影響する

ところが、Pythonの場合、インデントの位置が変わるだけで、コードの文脈も変わってしまうのだ。

つまり、以下のコードを実行すると、

for i in range(3):
    print('i=',i)         
for j in range(3):
    print('\tj=',j)

その実行結果は以下の通り。

i= 0
i= 1
i= 2
        j= 0
        j= 1
        j= 2

本来は 変数 i, j の2重ループを実行する予定であったのだが、それが単なるループを2回続けて実行する処理に化けてしまう。

こんな状況は良く起こるだろう。

つまり、プログラミングをしていて、エディタで表示されたコードの一部をカットアンドペーストで切り貼りしていると、インデントの位置が変わるなんて事は良くある。

その結果、自分が知らない間に、勝手にコードのロジックが変わってしまっているのだ。

あかんがなPython。

Visual Studio環境ではPython編集がやり辛い

さらに困った事に、ワテが使っているVisual Studioの環境のエディタは、Pythonとの相性があまり良く無い。

例えば先ほどの2重ループのコードを再び掲載すると以下の通り。

ただし、先頭にコメントがある。

    #コメント
    
for i in range(3):
    print('i=',i)
   
    for j in range(3):
        print('\tj=',j)

かつそのコメント行はインデントの位置がその下に続くコードよりも一つ下のレベルに成っているとする。

実際のVisual Studioエディタの画面キャプチャは以下の通り。

 

この状態で、Visual Studioのエディタでコードを整形して綺麗にフォーマットしてくれる機能を使ってみる。

全選択(CTRL+A)しておいて、

CTRL+K, CTRL+D を連続して押すと整形機能が動く。

つまりコントロールキーを押した状態で、KとDを連続で押せば良い。

その結果、こんな風になってしまうのだ。

その画面キャプチャは以下の通り。

コメント行の下の for i ループのインデント位置が勝手に一つ下がり、上のコメント行と同じ深さになってしまう。

その結果、unexpected indent なんてエラーが出ているし。

この場合はエラーメッセージが出たので気づいたのだが、もしエラーメッセージが出ないようなインデント変化が起こった場合には、コードを整形した瞬間にプログラムのロジックが勝手に変わってしまってバグが入り込む事になる。

あかんがなPython。

いや、あかんがな Visual Studioなのか?

それならワテがPythonを拡張してPython++を提唱

エディタによるインデント位置変化問題の画期的な解決方法を思い付いた。

Pythonの文法を拡張して、必要ならforやifブロックをカッコ{・・・}で囲っても良いようにすればいいだろ。

こんな感じだ。

    #コメント

for i in range(3):{
    print('i=',i)
   
    for j in range(3):{
        print('\tj=',j)
    }

}

ワテ独自拡張のPython、名付けてPython++なんてどうかな?

これならC、C++、C#系の人にも馴染みやすい。

カッコ{}を付けないpython本来の書き方をミックス出来る仕様にしておけば良い。

なので、ワテが経験したようなコードのコピペでインデント深さが勝手に変わってしまい、ロジックの意味も変わってしまうような問題を避けたい人は { } を使ってコードを書く。

エディタは必要に応じてそのカッコ { } の表示・非表示を切り替えられる。

あるいは、カッコを除去したファイル出力も出来る。そんな機能をエディタに追加しておけば実用性は高い。

最終的に納品するPythonコードはカッコ { } を除去した純正Pythonファイルで出力、そう言う運用でいいんじゃないかな。

と言う事で、forブロックやifブロックをカッコ { } で囲っても良い拡張Pythonは、ワテの命名でPython++と呼びたい。

どう、この画期的なアイディア!?

ここにPython++の誕生である。

完璧や!!

Visual Studio 2017のPythonデバッガーが直ぐに制御不能に陥る

ちなみに、Visual Studio でPythonをデバッグしていると、Visual Studioが固まってしまい制御不能に陥り易い。

再現性もほぼ100%ある。

再現するのは簡単で、例えば、ブレークポイントをセットしておいて、ブレークしたらローカルウインドウにある変数の中身などを確認しているだけでほぼ確実にVisual Studioが固まる。

処理に時間が掛かっています
    [キャンセル]

こんなダイアログが出るのだが[キャンセル]をクリックしてもボタンが凹まない。

つまりイベントを受け付けていないのだ。

つまり、Visual Studioが完全に制御不能に陥っている。

対策は、タスクマネージャーからVisual Studioのプロセスを終了するしかない。

益々あかんがな。

まとめ

自称、プログラミング言語評論家のワテの感想であるが、恐らくPythonを設計した人は既存の言語が持つカッコ {・・・} を使った文法に変わる新しい文法を採用したかったのだと思う。

まあその点は理解出来るのだが、カッコを排除してしまった為に、コードの文脈を決める物がインデントの深さになってしまった。

つまり、自分で勝手にインデントの深さを決められないのだ。

forループなら次の行は一つインデントを入れなければならない。

for i in range(3):
     print('i=',i)

それをこんな風にすると文法エラーだ。

for i in range(3):
print('i=',i)

Pythonのそんな言語仕様は、誰がコードを書いても似た様なコードになると言うメリットはあるのは分るし、その特徴はPythonの長所として良く聞く。

でもなあ、プログラムなんて長い物だと何万行、何十万行、いや何百万行にも達する訳なので、多くの人の色んな個性によって作られたコードが混じって当然なのだ。

その個性を出来る限り排除して、誰が書いても似た様なコードにする必要があるのか?

ワテの意見では、そんな必要は全く無いと思う。

なぜなら、「似た様なコードになる」と言う程度では、大規模プログラム開発に於いて大きなメリットが有るとは思えない。

誰が書いても「完全に同じコードになる」と言うのであれば価値はあると思うが。

ワテに言わせれば、Python設計した人は無理やりカッコを使わない文法にしたかっただけだと思う。その結果、インデント問題を解決出来ないままPython言語を作って公開してしまった。

と思うのだが。

インデントが一個ずれただけでロケット打ち上げ失敗!

インデントの位置がコードのロジックに深く関与している副作用として、エディタでコピペした瞬間に自分が気付かないうちにインデント位置が変わってしまい、ロジックが変わってしまう欠陥がある。

それはVisual StudioのPythonエディタが悪いのか、それともPythonの設計が悪いのかと問われれば、それはPythonの設計の問題だろう。

今回記事で紹介したような二重forループの場合には、うっかりインデント位置が変わってしまっても文法的には正しいので実行時にはエラーは出ない。でも、当初予定していた処理結果とは異なってしまう。

つまり誰にも気付かれないバグがPythonソースコードの中に埋め込まれてしまうのだ。

このPythonのインデント位置問題でワテのテストプログラムで問題が出る程度なら世間には影響は無いが、例えばロケットとか人工衛星の制御プログラムにPythonが使われたとして、打ち上げたら爆発して失敗。

原因を調べたら、コピペで貼り付けたPythonソースコードがインデント位置が一個だけずれた事が原因だった!なんて事態も起こり得るだろう。

はっきり言って、プログラムロジックがインデントに強く依存するPhtyonの言語仕様は重大な欠陥がある。

Python特有のインデント問題を解決する為の画期的なアイディア

そして、そのPython特有のインデント問題を解決する為の画期的なアイディアを紹介した。

必要に応じてコードブロックをカッコ { } で括っても良いと言う仕様を追加する案だ。

名付けて『Python++』、商標登録しておこうかなw

そんな事をすればPythonの設計思想を台無しにする!と言う意見も出るかも知れないが、何事も安全策を講じておくべきだ。

カッコが付かないので見た目がスッキリするなんて言う軟弱な意見よりも、カッコで確実に括っているのでインデント問題なんて完全に排除できるという安心感の方が良いに決まっている。

ソースコードに美しさなど求める必要は無い

プログラムなんて見た目がスッキリしようがしまいが、そんな事はどうでも良い。

目的のロジックを正しく実装出来ていれば、ソースコードの見た目なんてどうでもいいんだ。

一つの関数が5千行あろうが、forループが6重入れ子になっていようが、ifやswitchが訳分からんくらい入れ子になっていようが、動けばいいんだ。

ソースコードに美しさなんて求めようとしているのは、プログラミング初心者だと思う。

強いて言えば、正しく動くプログラムこそ美しいのだ。

カッコが無ければ見た目がスッキリするなんてのは、ソースコードを10万行くらい書けば、そんな事はどうでも良くなる(ワテの場合)。

そうだろ!?

一つの関数が5千行有ったとして、それが複雑で難解だと思うのは程度の問題だ。

人間にとっては難解かもしれないが、人類を遥かに上回る知的生命体や人工知能が存在するなら、5千行だろうが5兆行だろうが一瞬でその関数の意味を理解出来るだろう。

難解な数学の定理の証明が、数百ページの論文なんてのは良く聞くが、人間ならそれを読むのに数カ月掛るかも知れないが、全能の神なら数億ページの論文でも一瞬で理解出来る。

だいたい、億とか兆とか言う単位でさえも、人類が普段扱っている大きな数字の概念だ。

でも、数字は無限大まである訳なので、高度な知的生命体なら例えば101000くらいの数字を普段扱っているかも知れない。今日は、101000円の宇宙船を買い物をしたとか。

そう言う知的生命体から見れば、5千行とか5兆行とかは、誤差の範囲だろう。

今の人類はそんな全能者には到底成れないので、カッコの有無なんて言う些細な事に拘らずに、目的とするプログラムを最短で完成させるのが人類に出来る最善の努力なのだ。

まあ、自称プログラミング言語評論家のワテであるが、Pythonの経験はまだ数日なので、もう少し使い込んでから改めて感想を書いてみたい。

Pythonの本を買う

独学プログラマー Python言語の基本から仕事のやり方まで

本日の時点で、アマゾンランキング7位(コンピュータ・IT分野)と言う超人気の書籍だ。

Python習うならこれを買え!と言う人気の教科書なのか?

コーリー・アルソフ

清水川貴之

お二人とも、知らない人だ。

ちょっと調べてみるかな。

多分、Python業界では有名人なのかもしれない。

もし機会があれあインデント位置が勝手に変わるとコードのロジックが変わってしまうと言うPython弱点はどう思っているのか意見を伺いたいものだ。

スポンサーリンク
ワテ推薦のプログラミングスクールで学ぶ
コメントを読む

この記事には読者の方からコメントが 4件あります。
興味ある人はこのページ下部にあるコメントを参照下さい。

Python
スポンサーリンク
warekoをフォローする
スポンサーリンク
われこ われこ

コメント

  1. 匿名 より:

    同意見です。
    コピペの際に、とても気を使わなきゃならなかったり、自動整形ツールは便利な反面、勝手にロジックを変えてないか不安になります。
    Pythonは人気ある事が不思議です。

  2. wareko より:

    匿名様
    この度は、小生のブログにコメントを頂きましてありがとうございます。
    私の場合、Pythonはまだまだ初心者なのですが、当記事はそのPythonを少し使ってみた率直な感想です。
    やはりインデント位置が変わるだけでプログラムのロジックが変化するのは神経を使いますよね。
    そんなPythonのインデント位置問題に関して私と同じ意見を持っている人が世の中にいる事を知って安心しました。
    今後、Pythonが改良されてこのインデント位置問題が改善されると良いのですが。
    私が提唱したPython++が採用されるなんて可能性は無いかな。
    無いな。
    では、また、お気軽に小生のブログにご意見やコメントなどをお寄せ下さい。

  3. 匿名のとくさん より:

    デザインと歴史
    ・Python はなぜ文のグループ化にインデントを使うのですか?
    https://docs.python.org/ja/3/faq/design.html

    4.Visual Studio環境ではPython編集がやり辛いの章でコードがズレた原因
    pep8-ja
    ・ブロックコメント
    https://pep8-ja.readthedocs.io/ja/latest/#id19

    参考にしてみてください!

  4. wareko より:

    匿名のとくさん様

    本日は小生のサイトに訪問頂きまして有難うございました。
    Pythonに関する情報有難うございます。

    さっそく教えて頂きましたURLを拝見させて頂きました。
    Visual Studioの環境でコードがズレた理由はブロックコメントの挙動と言う事で良いでしょうか?
    他のエディタでPythonを編集した経験は無いのですが、今回記事で紹介したようなケースでコードを整形した場合、Python編集に適したエディタならVisual Studioの挙動とは異なる動きをするのでしょうか?

    いずれにしましても、今のところやはりPython特有のインデント問題には、私は馴染めていません。
    Pythonプログラミングをしている世の中の多くの人は、インデントが原因のトラブルに巻き込まれるなんてのは、滅多にないのでしょうか?
    疑問が深まるばかりです。
    では、また何か良い情報がありましたらお教えください。