読者です 読者をやめる 読者になる 読者になる

The Zen of Python 解題 - 後編

python joke

The Zen of Python 解題 - 前編

"The Zen of Python" の役割

"The Zen of Python" は Tim Peters氏が1999年に「Pythonらしさとはなにか?」と問われて書き上げたものであることは前述した。Python 2.0 のリリースに向けて活発に開発が進められていたころである。

この Python 2.0 は、いろいろな意味で重要なリリースだ。まず、Python著作権の帰属、ライセンス等について数々の「大人の話し合い」をくぐり抜け、現在の PSF (Python Software Foundation) による安定した体制を築き上げる第一歩となった、記念すべきリリースである。

また、このリリースでは リスト内包(例 [x*x for x in range(10)]) や累積代入文(例 a += 10) などの Python 文法の拡張が行われた。従来、Python は「ミニマリストの言語」と呼ばれ、文法は出来る限りシンプルに押さえて余計なシンタックスシュガーは採用しない、というイメージを持たれていたのであるが、このリリースでは、意味のあるユースケースさえあれば、このような他の構文で代用可能な構文であっても取り入れられる、ということが示された。

この時、「これから PythonPerl のような、野放図な拡張が次々と加えられてしまうのだろうか?そうなったらそれは "Python" なのか? PythonPython らしくあるために、何か指針が必要ではないか?」という声があがった。この声に答えて公開されたのが、"The Zen of Python" だ。

従って、"The Zen of Python" は Python 開発する人々へのガイドラインであり、Python 開発する人へ向けたものではない。もし "The Zen of Python" が気に入らなければ、完全に無視してしまっても全く差し支えないのである。"The Zen of Python" の価値は、それを読む人々が決めるべきである。

では、Python開発者たちは "The Zen of Python" を金科玉条としてきちんと守っているのだろうか?実は、そうでもない。Pythonの進化に従って、 Zen に反するような機能も増えてきている。原則は原則として尊重しても、最終的には実用性を重視するのが Python の Zen なのだ。

Zen 解説

もう一度、"The Zen of Python" 全文をここに掲載する。

 1. Beautiful is better than ugly.
 2. Explicit is better than implicit.
 3. Simple is better than complex.
 4. Complex is better than complicated.
 5. Flat is better than nested.
 6. Sparse is better than dense.
 7. Readability counts.
 8. Special cases aren't special enough to break the rules.
 9. Although practicality beats purity.
10. Errors should never pass silently.
11. Unless explicitly silenced.
12. In the face of ambiguity, refuse the temptation to guess.
13. There should be one-- and preferably only one --obvious way to do it.
14. Although that way may not be obvious at first unless you're Dutch.
15. Now is better than never.
16. Although never is often better than *right* now.
17. If the implementation is hard to explain, it's a bad idea.
18. If the implementation is easy to explain, it may be a good idea.
19. Namespaces are one honking great idea -- let's do more of those!

以下は @yasuii による 日本語訳である。

 1. きたないのよりきれいな方がいい
 2. ごちゃごちゃ難しいのより、白黒はっきりしてるのがいい
 3. めんどうなのよりかんたんな方がいい
 4. けど、訳分かんなくなるくらいならめんどうな方がまし
 5. ネストさせなくていいならしない方がいい
 6. たくさん詰め込んだのよりスカスカな方がいい
 7. 読みやすさがたいせつなのよ
 8. 特別なこともあるけど掟破りってほどじゃない
 9. 実用性を求めてくと、ちょっとはずれちゃうこともあるけどね
10. わざとそうしてるんじゃない限り
11. エラーをだまって通すようなことがあっちゃいけません
12. あいまいなことをてきとーに処理しちゃいけません
13. 間違えようのないやり方がひとつだけあるのがいいね
14. オランダ人以外には、ちょっと分かりにくかったりしてもね
15. やらないよりは今やるべき
16. けど今「すぐ」やるならやんない方がいいこともある
17. 作るものをうまく説明できないようならそれはボツ
18. うまく説明できたらたぶんそれがグッド
19. ぶらぼーなアイディア名前空間、やっぱこれですね

前置きが長くなった。ここからは、個々の Zen を詳しく見ていこう。

1. Beautiful is better than ugly.

美しさにも色々な種類があり、また様々な観点がある。ここでは Python スクリプトに美しさ・読みやすさを求めた Zen と考えるのが適当だろう。読みやすさを確保するには色々な方法があるだろうが、Python ではできるだけ記号に Python 独自の特別な役割を持たせず、英数字を中心として言語を構築している。加えて、

6. Sparse is better than dense.

も又、読みやすさのための指針である。短くてみっちり詰まった賢い一行よりも、素直に論理や構造をわかりやすく示した方がよい。この Zen は、Python三項演算子を取り入れるか否かの論争で反対派の強い論拠となった。

if cond:
    a = 100
else:
    a = 200

a = 100 if cond else 200

はどちらが読みやすいだろうか?この程度のスクリプトでは三項演算子でも十分読みやすいが、

if cond1:
    a = 100
elif cond2:
    a = 200
elif cond3:
    a = 300
else:
    a = 400

a = 100 if cond1 else 200 if cond2 else 300 if cond3 else 400

と書くことは許されるのだろうか? 許されるとしたらそれはなぜか?許されないとするなら、それは常にだろうか?

そして、Python の読みやすさへのこだわりは、最終的に

7. Readability counts.

へと結実する。

Perlなどのプログラム言語が時に Write only language (書くことはできても読んで理解することが不可能な言語)と揶揄されるのとは対照的に、Python では伝統的に読みやすさを重視する。書きやすさと読みやすさを秤にかければ、常に読みやすさに重きをおくのである。「キーボードのタイプ数を節約する」という動機が受け入れられることは、まずない。

「でも、急いでいるときは少しでも速く書けた方がよい」そう思うだろうか? しかし、書くのはたったの一度きりだが、そのスクリプトは何回読まれることになるのだろう?よほど簡単なアプリケーションであっても、最終的に完成するまでには10回や20回は目に触れることになるだろう。その時間を考えれば、急いでいれば急いでいる時ほど、読みやすさに注意するべきである。読みやすさを無視して書く時間を節約するのは、悪い最適化だ。

2. Explicit is better than implicit.

Python では、プログラムの動作はできるだけ明示的に記述されるべきだ、とされる。これはすなわち、

12. In the face of ambiguity, refuse the temptation to guess.

で示されるように、「こう書いてあったら、プログラマの意図はきっとこうだろう」という決めつけをせずに、あいまいな点があればそれはエラーとしてしまうのである。

しかし、あまりに厳しすぎてはかえって害となる。型チェックの厳しいプログラム言語では整数と浮動小数の足し算もエラーにしてしまうことがあるが、これは Python のような動的なスクリプト言語ではいささか厳しすぎるように思われる。実用性を考えれば許容するべきだろう。しかし、Perl のように整数と文字列の足し算までも許容してしまうのはどうか?この場合は処理や入力データに誤りがある可能性が高いと考え、エラーとなっている。

なんと言っても Pythonスクリプト言語であり、スクリプト言語プログラマが考えるべきことをできるだけ減らし、効率的に開発を進められるのが身上だ。ある程度は融通を利かせ、プログラマの「意図」を推測する必要がある。この2条の Zen は、「スクリプト言語としては」と但し書きをつけて解釈されるべきだろう。

ただし、

10. Errors should never pass silently.
11. Unless explicitly silenced.

で示されるように、融通を利かせすぎて発生したエラーを隠すようなことがあってはならない。エラーの発生を抑止できるような場合でも、デフォルトではエラーを検出するようにし、明示的な指定があった場合のみ抑止するべきである。代表的な例としては、ユニコードとバイト文字列の変換が上げられる。

unicode(bytestring, encoding="ascii")

では、bytestring に日本語などの ASCII ではない文字が含まれている場合は例外が送出される。自動的に不正な文字を排除したければ、

unicode(bytestring, encoding="ascii", errors="ignore")

のように明示的にその指定をする必要がある。

余談だが、残念ながら Python にはこの Zen が守られていないケースも存在する。たとえば、

>>> class Spam(object):
...     def __getattribute__(self, name):
...         print "*** 0除算を実行 ***"
...         1/0
...
>>> obj = Spam()
>>> obj.bar
*** 0除算を実行 ***
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __getattribute__
ZeroDivisionError: integer division or modulo by zero

では、Spam オブジェクトのメンバーを参照すると必ず 0除算の例外が発生するようになっている。しかし、ここで hasattr() 関数を使ってメンバーを参照した場合、

>>> hasattr(obj, "bar")
*** 0除算を実行 ***
False

のように、例外が発生しても hasattr() はその例外を隠してしまうのである。

3. Simple is better than complex.

もちろん、プログラムはより単純に記述できれば、それに越したことはない。

4. Complex is better than complicated.

しかし、単純に記述するための余計な仕組みを入れすぎると、ややもすると複雑な処理を書くときには複雑怪奇な書き方をしなければならなくなったりしてしまうのだ。この2つの Zen は、 Perl の開発者 Larry Wall の以下の発言とほぼ同じ意味合いである。

Perl is designed to make the easy jobs easy, without making the hard jobs impossible
(Perlは簡単なことは簡単に、難しいこともそれなりに出来る言語として設計されました)

従って、

8. Special cases aren't special enough to break the rules.

ある特定のケースで非常に効果的なアイデアであっても、そのケースはそれほど一般的ではないかもしれないし、またその修正によって、別の部分で悪い影響を及ぼしてしまうかもしれない。処理は効率的になっても、あまり Python 的とは言えないアイデアかもしれない。機能追加の採用には十分な吟味が必要なのである。

とはいえ、多少の不都合があったとしても、

9. Although practicality beats purity.

最終的には実用性で判断されるべきだ。たとえ既存のアプリケーションとの互換性に問題があっても、オブジェクト指向パラダイムにそぐわなくても、"The Zen of Python" に違反していたとしても、その実用性が支払う犠牲に見合ったものであれば採用されるべきなのである。

5. Flat is better than nested.

Python の標準ライブラリはjavaなどと異なり、階層構造を採用していない。Javaなら ライブラリは java.lang や java.math などに細々と分割されているが、Python ではファイル処理モジュールもインターネット通信モジュールもすべて横一列に並んでいるだけだ。ドキュメントを参照するときにはモジュールの分類は便利なものであるが、いざそれを使う段になっては特に必要のないシロモノである。

13. There should be one-- and preferably only one --obvious way to do it.

この Zen は Perlの有名なモットー "There's More Than One Way To Do It." (やり方はひとつじゃない) に対抗して作られた Pythonのモットー "There's Only One Way To Do It"(たった一つのやり方) の書き換え版である。 Perlのモットーは "TMTOWTDI" と呼ばれるのに対し、Python版は "TOOWTDI" と呼ばれる。Perl ではプログラマの個性に応じた多様な書き方を推奨しているが、Python では逆に、同じ処理ならだれもが同じような記述をすることを目標にしているのだ。

もちろん、この Zen の実現は容易ではない。

14. Although that way may not be obvious at first unless you're Dutch.

最善の書き方というのは人によって異なるものである。特にオランダ野郎が何を考えているかなんて、我々の知ったことではないのだ。 (注: Pythonの開発者 Guido van Rossum はオランダ人)

また、"one obvious way" は時とともに変化する。Pythonの進化により、これまでは "one obvious way" だったものが次善の手段になってしまうことがあるのだ。たとえば、昔のPythonで辞書に含まれるすべてのキーを参照する場合、

for k in dict_obj.keys():
    ...
    ...

のように書くのが普通であったが、最近の Python では

for k in dict_obj:
    ...
    ...

が普通となっている。しかし、別のより良い方法が利用可能になった場合でも、過去との互換性を保つために古い方式を削除することはできない。このため、どうしても "one obvious way"、"やや obvious way"、"そこそこ obvious way"、"去年までの obvious way" などが混在してしまうのである。

この Zen は lambda不要論の根拠として、"6. Sparse is better than dense." とともに使われることが多い。

return lambda arg: return arg*10

と書くより、若干行数が増えても

def func(arg):
    return arg*10

return func

で十分とする説である。

15. Now is better than never.
16. Although never is often better than *right* now.
17. If the implementation is hard to explain, it's a bad idea.
18. If the implementation is easy to explain, it may be a good idea.

これらの4つの Zen は、Pythonに変更を加える場合に注意すべき点を示している。難しいからといって、尻込みしてばかりではいけない。時にはまずチャレンジし、その反応を見るというやり方も有効だ。しかし、焦りすぎてはならない。十分な時間をかけ、慎重にその有効性や副作用を見極めるべきである。

また、あるアイデアの実装方法を明快に説明できないなら、そのアイデアはユーザが明快に利用することができないアイデアであることが多い。実装方法がいくら複雑でも、ユーザが理解しやすいアイデアであれは実装方針の概略程度はすっきりと説明できるものである。実装方針からして複雑で説明困難なのであれば、それはとてもユーザが理解できる機能ではないだろう。

19. Namespaces are one honking great idea -- let's do more of those!

Pythonではモジュール・関数・クラス・文字列・数値など、すべての要素はオブジェクトであり、実行時にはその所属するスコープに応じた名前空間に格納される。関数内のローカル変数であればローカル名前空間、モジュールに直接記述されたオブジェクトならグローバル名前空間に所属する。

名前空間と言うとちょっと難しそうだが、その実態は単なる辞書オブジェクトである。変数名と、その値が登録された辞書オブジェクトにすぎない。普段 Pythonプログラミングに利用している辞書オブジェクトが、そのまま名前空間として利用されているのである。

Pythonのスコープは単純であり、ちょっとした知識があればデバッグ用にローカル変数の一覧を出力したり、オブジェクトのイントロスペクション機能を開発したりするのは非常に簡単である。そういった機能を開発する場合でも、専用のAPIをわざわざ学ばずとも、通常の辞書オブジェクトの操作だけで高度な目的を達成することができるのだ。 Python名前空間は、Python の生産性と柔軟性を支える重要な柱の一つである。

(注:ただし、近年では各種最適化のためそう単純には言えなくなってきた。"The Zen of Python" が書かれた頃、Python は今より遙かに原始的だったのだ)

終わりに

予想外の長文となってしまったが、以上で "The Zen of Python" の解説を終える。

本解説は これまでに私が見聞きした議論(主に comp.lang.python/python-devなど)や、 Guidoの PythonDC 2003 におけるキーノートスピーチ 等を元に、私の Pythonista としての経験を踏まえて書き上げたものだ。 冒頭にも書いたが、 Python はもはや非常に古いプロジェクトであり、現在となっては不合理とも思える部分が盲腸のように残されている。 Python3ではかなり改善されてはいるが、 古い Python の慣習をそのまま持ち込んでいる部分もあり、やはり理解のためにはPythonの歴史をある程度振り返っておくことは無駄ではないだろう。

そこで本稿では "The Zen of Python" を題材として、できるだけ古い Python コミュニティの雰囲気や考え方を伝えようと試みた。筆者個人の記憶や考え方が強く反映しているため、同意できない部分も多いかもしれないが。

本稿がPython学習の一助となれば望外の幸運である。