このサイトについて

Pythonのコードをきれいに書くためのTips

Pythonのコードをきれいに書くためのTips

Pythonのようなスクリプト言語の特徴の一つとして,データをソースコードに直接埋め込みやすい,というものがあると思います。実際,Pythonのコードを見ると文字列,リストや辞書といった高機能で使い回しのしやすいデータ型が,リテラルとしてソースコードに埋め込んであるのをよく目にします。時には変数に代入されたり,時には関数やメソッドの引数部分に埋め込まれたり。

いちいち離れた場所にあるデータを見に行ったり,オブジェクトを作るための宣言をする必要がなく,処理をしたい場所の間近にデータを埋め込めるので,とても便利なのですが,欠点もあります。無造作にデータ型のリテラルを埋め込んでいると,ソースコードが横に長くなって,見にくくなってしまいます。可読性が低くなるわけですね。可読性の悪いコードを書くことは,Pythonの文化に反します。すべてのソースコードは見やすくあるべきです。Pythonでは80文字くらいでソースコードを改行すべき,という暗黙のルールがあります。横に長くなったソースコードは,適当な位置に改行を入れると見やすくなります。

インデントでブロックを表記する特徴から,Pythonはホワイトスペース(空白)に厳密な言語だと思われがちです。しかし,一面ではこれは間違っています。Pythonは,2,3のルールを守りさえすれば,空白について寛容に対処してくれます。ここでは,改行をうまく活用して,Pythonのコードを見やすく整形するTipsをいくつか紹介します。

長い文字列をきれいに埋め込む

文字列は,ソースコードの横幅が長くなる原因の代表格かもしれません。たとえば,パスワードチェック時に気の利いたメッセージを例外として投げたいとします。

....

if 8 > len(password) or len(password) > 24 or re.match(r'(\w+)', password):

    raise ValueError(" '%s'はパスワードとしては適切ではありません。パスワードは8文字以上24文字以内で、'_'と英数字で構成してください。英字の大文字,小文字は区別されます" % password)


イヤですね。
長い文字列をきれいに埋め込むために,トリプルクオートが使えます。

....

if 8 > len(password) or len(password) > 24 or re.match(r'(\w+)', password):

    raise ValueError(""" '%s'はパスワードとしては適切ではありません。

パスワードは8文字以上24文字以内で、'_'と英数字で構成してください。

英字の大文字,小文字は区別されます""" % password)


改行が入るのがイヤな場合は,末尾にバッククオート(\)をつけましょう。
インデントを維持したい場合は,カッコを使います。カッコに続けて,複数の文字列を並べます。このとき,文字列の間にコンマは使わないようにします。カッコ内の文字列が自動的に連結されて,一つの文字列になります。

....

if 8 > len(password) or len(password) > 24 or re.match(r'(\w+)', password):

    raise ValueError( (" '%s'はパスワードとしては適切ではありません。"

                       "パスワードは8文字以上24文字以内で、'_'と英数字で構成してください。"

                       "英字の大文字,小文字は区別されます") % password)


リスト,タプル,辞書などのリテラルをスマートに埋め込む

リスト,辞書,タプルなどの組み込み型もコードを汚くする原因になりがちです。多くの要素を含むデータ型のリテラルを記述するときが要注意。

for name in ('name', 'furigana', 'postal', 'address1', 'address2', 'company', 'organization', 'comment'):

    print """<input type="text" name="%s">""" % name


105文字もありますよどうしましょう。
Pythonはカッコの中の改行や空白文字列にはとても寛容です。カッコの中で改行したり,自由に空白文字列を使うことが出来ます。

for name in ('name', 'furigana', 'postal', 'address1',

             'address2', 'company', 'organization', 'comment'):

    print """<input type="text" name="%s">""" % name


要素の多い辞書を定義するときにも,同様のテクニックが利用できます。

neko = {'name':'我が輩',
        'age':4,
        'birthplace':'東京',
        'introduction':("""吾輩は猫である。名前はまだ無い。"""
                        """どこで生れたかとんと見当がつかぬ。"""
                        """何でも薄暗いじめじめした所で"""
                        """ニャーニャー泣いていた事だけは記憶している。"""
                        """吾輩はここで始めて人間というものを見た。""") }

関数やメソッドの呼び出し,定義

関数呼び出しにデータ型のリテラルを埋め込むとソースコードが横に長くなりがちです。

import urllib, urllib2
r = urllib2.urlopen('http://foo.bar.com/post_something', urllib.urlencode({'name1':'value1', 'name2':'value2'}))

カンのいい人なら,関数呼び出しもカッコで囲まれていることに気づくはずです。Pythonの「カッコの中では寛容」という特徴を使うと,こんな風に書けます。

import urllib, urllib2
r = urllib2.urlopen('http://foo.bar.com/post_something',
                    urllib.urlencode({'name1':'value1',
                                      'name2':'value2'}))

メソッドや関数の定義も同様で,改行や空白を入れることが出来ます。

def foo(arg1, arg2,
        arg3 = "some default string",
        arg4 = ('value1', 'value2', 'value3'))
    # do something

長〜いimport文

import文もコードを横長にすることがありますね。これは実際に私が書いたPloneのコードです。

from Products.ATContentTypes.content.base import registerATCT, ATCTFileContent, updateActions
Python 2.4からは,import文でカッコが使えるようになりました。カッコの中では,当然改行や空白を使うことが出来ます。

from Products.ATContentTypes.content.base import (registerATCT,
                                 ATCTFileContent, updateActions)

インターネット上で公開されているPythonのソースコードには,これらのテクニックがよく使われています。テクニックを知ることで,自分のコードをきれいに書けるようになるのはもちろんですが,他の人のソースコードも読みやすくなるはずです。
2010-08-27 04:49