2010年06月25日

【Pythonic化】POST METHOD時の情報取得に「リスト内包表記」を使う

 リスト内包表記は、for文によるループ処理をリスト内に記入してしまうという一見トリッキーなPythonの規格である。当方の様に古いpythonユーザの中には、未だに認識が足りず、知ってはいても使わないで済ませてしまう輩が多いと思う。何故かって言うとわざわざ使わなくてもシステム作りに支障はないからである。ところが、「エキスパートPythonプログラミング」を読んでみると、同じ働きをするものをリスト内包表記に変えると処理効率が良い(詳しくは買って読んでくれ^^;;)とのことなので、「そろそろ使って試るか」というのが、本日のお題である。

 この手のものは具体的にメリットのある課題を思いつかないと使おうとしてもなかなか実現しない訳だが、前稿のcgi のpost method時に使えなくなる場合のある「mire.htm.cgi_params()」の代わりとして、先ずは使って試ようと思う。

 具体的に、for文で普通にコーディングすると次の様になる。
import cgi
params = {}
for f in cgi.FieldStorage().value:
params[f.name] = f.value

 これをリスト内包表記にすると、[辞書キー, 値]形式のリストを要素とするリストを辞書化するdict()コンストラクタの助けを借りることで行を2つ削減出来る。
import cgi
params = dict([[f.name, f.value] for f in cgi.FieldStorage().value])

 元々、cgi_params()関数を作成したのは、FieldStorage()メソッドを忘れてしまうことが多かったし、思いだしてもスペルミスしてしくじったりということも少なくなかった経験から、cgi上のパラメータを取得するという目的を達成する関数として名前を決めカプセル化したものなので、何れはその置き位置に関係なく確実に利用出来る様にしてしまうつもりだが、そうなる迄は、このリスト内包表記を利用することも選択肢の一つだろう。

 尚、cgi_params()の引数としてcgi.FieldStorage()を渡す手法も含めて、cgiモジュール関連の処理を含むモジュール読込み以前に置くことで確実にPOST METHODでCGIのパラメータの受信が出来ると思う(あくまで思っているだけ)ので、もし、当方のmire.htmモジュールを盲信して利用した結果、同様にPOST METHODで不具合が発生しているなら、その様に修正して試て欲しい。

 気持ち的には、セキュリティ上params変数で全パラメータを保持する形はとりたくないのだが、致し方ない。

 特に解説は必要ないと思っていたが、読みかえして試るとまあ、参考リンク程度はあった方が親切かなと思ったので追記して置く。何れも、お馴染のオンライン上のPythonチュートリアル内のページなので重箱の角の特別な内容でない一般的な内容であることが判ると思う。


 ついでに、同じページ内の「5.6 ループのテクニック」にある「iteritems() メソッド」と「enumerate() 関数」も活用機会は多いと思うので、頭に入れて置くと良いだろう。

 enumerate() 関数は、「エキスパートPythonプログラミング」でも触れらていたが、リスト全体をfor文で処理する際にインクリメン変数を別途準備して使っている様な場合、ループ外の「i = 0」という初期化とループ内の「i = i + 1」の行が不要となる分スマートな表記が出来る。
 例えば、リストitem_list内の要素全てに2を掛けたものに変換する場合、通常
item_list = [1, 5, 7, 3, 4]
i = 0
for item in item_list:
item_list[i] = item * 2
i = i + 1
enumerate() 関数を使うと
item_list = [1, 5, 7, 3, 4]
for i, item in enurate(item_list):
item_list[i] = item * 2
の様に簡潔な記述が可能だし勿論この程度に簡単だとリスト内包表記化で
item_list = [1, 5, 7, 3, 4]
item_list = [item * 2 for item in item_list:]
と書くことも可能^^;;だか、idそのものを使う必要がある場合にはenurate()関数を併用で解決出来る。

 また、「iteritems() メソッド」は、辞書の処理でkeys()メソッドを使い予め要素の並びを変える整える必要がない場合に使うとenumerate() 関数同様に画一的にスマートな記述が出来る。

 蛇足ながら、今回の用例では不要だったので省略され、存在しないが、リスト内包表記にはif文を附記しより柔軟なフィルタを記述することが出来る。例として適当ではないかもしれないが、CGI引数の中で「hidden_」で始まるものを除く場合は次の様になる。
import cgi
params = dict([[f.name, f.value] for f in cgi.FieldStorage().value if not f[:7]=='hidden_'])

 また、当方が今主に利用しているものはPython2.6なので、このリスト内包表記はリストを返しているが、Python3.xではイテレータを返すことになりメモリー処理的にはより効率よくなるそうである。ということで、何れ3.xに切替えれば何もしなくても改善出来るので、その辺は気にしないで使うことにしている。
posted by Mire at 23:19 | Comment(2) | TrackBack(0) | Pythonプログラミング | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
エキスパートPythonプログラミングをお読みいただき、ありがとうございます。
同じく本書に書いてある、ジェネレータ内包表記により、次のようにさらに効率的に書くことができます。

params = dict((f.name, f.value) for f in cgi.FieldStorage().value)

Python 2.7 や Python 3 では、さらに辞書内包表記を使うことができます。

params = {f.name: f.value for f in cgi.FieldStorage().value}
Posted by methane at 2010年06月26日 12:59
コメント有難うございます。また、レスが遅れてすみません。何故か、コメントが承認待ちになっていました。そんな設定をしているつもりはないので、設定を調べて見ているのですが、原因が判りません。暫くは、管理画面でコメントの到着確認と設定変更箇所の捜索をしなければならない様ですね。

 さて、当方では使用ライブラリの関係でPython2.x系の利用なので、ご教示頂いたものは使えませんが、よりすっきりした表現に出来ますよね。

 また、methaneのこの御本、とても役に立っていますよ。Skillは兎も角、当方はPython歴だけは長いので、自然と昔ながらの伝統的な互換表記の利用が多くなってしまいます。そんな人間にはとても良い処方箋です。Python本は少ないけど、いったん使える様になると、必要なライブラリさえ探すだけで、使えてしまうのがPythonなので、余り出版物には依存していませんが、この様な書籍は大歓迎です。出来ましたら今後も、この様な書籍を日本語で出して頂けると有難いです。
Posted by mire at 2010年09月01日 11:47
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
月額見放題1,000円開始キャンペーンバナー(画像ありver)
紺碧の艦隊 ルパン三世 GREAT CHASE クリックプロモーション
<< 2013年01月 >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
カテゴリ
タグクラウド
ファン
利用中のオープンソース
最近のコメント
最近の記事
過去ログ
QRコード
レガシーなアプリはいかが?
Dell 法人のお客様ページ
  • 【法人様向け】デル、お得なキャンペーン情報
  • 法人のお客様向け ストレージソリューション
  • 法人のお客様向け ネットワークソリューション
  • 【SOHO法人様向け】デル・オンライン広告限定ページ
  • デル-個人のお客様ページ
  • 【個人のお客様向け】デル・オンライン広告限定ページ
  • オンライン広告限定キャンペーンページ
  • ソフトウェア&周辺機器 パソコン工房
    ツートップインターネットショップ(twotop.co.jp) マウスコンピューター/G-Tune
  • ×

    この広告は1年以上新しい記事の投稿がないブログに表示されております。