pythonの@って

TurboGearsいじってたら、@exposeってのがあって、なんじゃろかーって初めてのpythonみたけど載ってなかった。

いろいろ、キーワード突っ込んでググってみたらやっとわかった。

IBM 魅力的な Python: デコレーターで魔法を身近に - Japan

最近ではバージョン 2.4 で「デコレーター (修飾子)」が拡張されています。デコレーターは、大抵のメタプログラミングを行う際の最新かつ、とびきりユーザー・フレンドリーな手段になります。

@expose("tgcommerce.templates.category")
def index(self):

はCatalystでいう

$c->stash->{template} = ...

sub end : ActionClass('RenderView') {}

と似たようなもんなのか。

いろいろ備忘録日記 - 01月23日の日記

デコレータとは、GoFのデザインパターンにある名前のやつと同じく なにかを修飾する機能を持つものです。pythonの場合は、 デコレート対象が関数およびメソッドになります。

あー、だから最初関数合成とかいう記述がみつかったのか。

関数合成みたいに考えると、MVCってCっていう関数でMをいじってVって関数でラップするって考えてもいいのか。

V(C(M))

みたいに。haskellだと

V . C . M

な感じになってんのかな。

タボギア教に入信することにしたヨ

blosxom重くてかなわんのでどうにかしようと色々考えた結果、TurboGearsで作ってみようかなと。

pythonマスターのきっかけになればと。

で、早速The 20 Minute Wikiなど作って感触を確かめてみた。モデルの管理をwebからできるのは楽。あとやっぱCatalystとは色々と違うなぁと。

CBlogでもいじって自分好みに仕上げていこうかな。

pythonで高階関数

Pythonでの関数プログラミングを流し読み。Xoltar使うと関数型言語っぽくかけるらしい。

ふつうのhaskell読んだあとなので、ここらへんの関数プログラミングの話題も楽しい。

第2回はクロージャとbindingの話でclosure()とやるとクロージャができ、Lispチックな書き方もできるらしい。第3回はカリー化の話で、これまたcurry()とかやるだけでいいっぽい。また、最後のほうの関数合成の話も面白かった。

ちなみにperlにもSub::Curryってのがあって、こんな感じで書ける。

sub foo { join "_", @_}
my $f = curry(\&foo, 1, 2);
my $f2 = curry($f, 3, 4);

print $f2->(5);

で、実行すると

$ perl curry.pl 
1_2_3_4_5

サブルーチンのリファレンスを指定すればいいだけのお手軽っぽいので、今度何かに使ってみよう。

あと、any()とかall()はQuantum::Superpositionsが使えるかな。

ProductName ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
青木 峰郎
ソフトバンククリエイティブ / 2940円 ( 2006-06-01 )


追記

perlで関数型のプログラミングをするモジュールとか

MeadowでPythonの対話型シェルを使う

Meadowいじってて、補完機能使ってたら偶然見つけた。

M-x run-python

meadow_python

Meadowからpython使えると便利。

pydocって-pオプションでWebサーバーになるのね

pydoc って

pydoc -p 8020

で、ドキュメントのウェブーサーバーとして動くということを知った。あとは

from pydoc import writedoc
import os, sys
import os.path

sys.path.append("../lib")

writedoc('PyModule')

とかやるとドキュメントがhtmlで書き出されるのね。pythonはここらへんが標準なので使い勝手がよい。perlだと pod2htmlでよいが、サーバーはPod::Webserverをインストールして

podwebserver

で動かせるらしい。

これはperl hacksで知った。

ProductName Perl Hacks: Tips & Tools for Programming, Debugging, And Surviving
Damian Conway
Oreilly & Associates Inc / 2163円 ( 2006-05-30 )


最初、を~便利かもとか思ったけど、ブラウザ使わないでperldoc とかperldoc -m で端末から眺めるほうが一番な気がしてる。

pythonモジュールのバージョンは

pythonモジュールのバージョンってどうやって調べるんだろうとか。
versionとかいう属性に統一されてると思ったんだけどそういうわけでもないのね。

>>> import rpy
>>> import re
>>> [x for x in dir(rpy) if re.search('version',x)]
['rpy_version']
>>> rpy.rpy_version
'0.4.6'
>>> import SOAPpy
>>> [x for x in dir(SOAPpy) if re.search('version',x)]
['__version__', 'version']
>>> SOAPpy.__version__
'0.11.6'

あと正規表現もモジュール読み込まないといけないのね。

追記

あ、別に正規表現使わなくてもfindでもいいのか。

>>> [x for x in dir(rpy) if x.find('ver') > -1]

「みんな」から「ダイブイントゥー」そしてフィボナッチ

みんなのpythonを読んだら、もうちょっと実践的なコードを基に、他の言語と比較しながら説明してあるDive Into Pythonなど読むべし。pythonの初歩からhtml,xmlの処理、そしてSOAPによる通信といった割と基本的な(けど実用的な)章があって、終わりのほうは単体テスト、リファクタリングといったテスト技法や、関数型プログラミングに関しても触れてるので、全体を読んでpythonへの理解はかなり深まった(と思う)。わからないところも、みんなのpython片手にPython ライブラリリファレンスひけば、大概解決したし。

で、17章にフィボナッチ数を求める例があって、そこでジェネレータ使ってたのをみてジェネレータって便利だと理解した。

def fibonacci(max):
        a,b = 0,1
        while a < max:
                yield a
                a, b = b, a+b

for n in fibonacci(1000):
        print n

とfibonacci関数定義するだけでフィボナッチ数が。perlで書いたのと同じようなアルゴリズムなのにperlより簡単にかけているのはyield文のせい。

ProductName みんなのPython
柴田 淳
ソフトバンククリエイティブ / ?円 ( 2006-08-22 )


060914追記

perlでもクロージャ使えば同じようにかけるわ。ということに朝起きたときに気づいた

sub fibonacci {
    my $max = shift;
    my ($fib,$a,$b,) = (0,0,1);
    return sub {
        ($fib,$a, $b) = ($a,$b, $a+$b);
        if ($a < $max){
            return $fib;
        }
    }
}

my $f = fibonacci(100);

pythonにもクロージャってあるんだろうけど、ジェネレータとの使いわけってどうなるんだろうか?

rpy

Statistics::RもRSPerlもイマイチ感が強かったので、rpyを使い始めているが、こんなに便利とは思わなかった。

というわけで、rpyで主成分分析を行い、できたモデルで新しいデータの主成分を求めてみるというサンプルを。  今回はrpyのテストなのでデータはrnormで作った。普通バイオインフォとかケモインフォなパターンだと、遺伝子の発現レベルとか、化合物のディスクリプターを使うけど。

>>> from rpy import *
>>> r.library('stats')
>>> a = r.matrix(r.rnorm(15),5)
>>> b = r.matrix(r.rnorm(15),5)
>>> model = with_mode(NO_CONVERSION,r.prcomp)(a)
>>> model
<Robj object at 0xb7f9f1c0>
>>> r.predict(model,b)
array([[ 0.28817526, -2.20038126,  0.42937523],
      [ 0.76682094, -1.38050702,  0.24898564],
      [-0.28308137, -0.51609132,  0.12062971],
      [-0.68531169,  1.42599763,  0.03987597],
      [-1.35685327,  0.02394946, -1.03868517]])

と数行ほどで、予測したいデータセットの主成分がpythonのarray型で返ってくるので、このあとの処理が凄く楽チンになる。

rpyはデータのコンバージョンのやり方だけきちっと押さえておけばあとはRと一緒に扱えるのだが、コンバージョンのモードが色々あって、初めのほうは悩まされることが多かった。特にモデルをRで適用する場合、python形式にコンバートしてしまうとRで扱えなくなってしまうのでNO_CONVERSIONモードにしないといけない。

Meadowにpython-mode

最近pythonに真面目に取り組んでいるので、Meadowにもpython-modeを入れた。

Emacs/Meadow2 - 2.00pre1

;;;Add python mode (setq auto-mode-alist (cons '("\.py$" . python-mode) auto-mode-alist)) (setq interpreter-mode-alist (cons '("python" . python-mode) interpreter-mode-alist)) (autoload 'python-mode "python-mode" "Python editing mode" t)

BiopythonはbioperlよりもPDBファイルの処理が速かった

みんなのpythonも読んだし、フレームワークでも試してみるかと、djangoとかTurbogearsに手をだしたら、火傷した。

djangoは一通りサンプル動作をさせることができたけど、Turbogearsはコントローラのあたりからさっぱりわからん。
いきなりフレームワークは無謀すぎたかなということで、Biopythonでも入れて、もう少しpython慣れすることに。

easy_install numpy

wget http://www.egenix.com/files/python/egenix-mx-base-2.0.6.tar.gz
python setup.py install

svn co http://www.reportlab.co.uk/svn/public/reportlab/trunk
python setup.py install

wget http://biopython.org/DIST/biopython-1.42.tar.gz
python setup.py install

easy_installはperlでいうところのcpanコマンドみたいで楽チンです(ちゃんと動けば)。動かないのは地味にダウンロード、展開、setup.pyを行なった。

さて、インストールも無事に終了したところで、bioperlと比べてみた。比較したのはpdbファイルの処理。というのは、FMO用のインプット作るときに使っているPDBパーザーつまりBio::Structure::IOがやたらと遅く、不満だったからというありがちな理由。

コードはこんな感じで、1fatっていうpdbファイル読み込んでCalphaを出力してみた。

python

from Bio.PDB.PDBParser import PDBParser

parser=PDBParser(PERMISSIVE=1)
structure=parser.get_structure("1fat", "1fat.pdb")
for model in structure.get_list():
    for chain in model.get_list():
        for residue in chain.get_list():
            if residue.has_id("CA"):
                ca_atom=residue["CA"]
                print ca_atom.get_coord()

perl

use strict;
use Bio::Structure::IO;

my $pdb_file = "1fat.pdb";
my $structio =  Bio::Structure::IO->new(-file => "$pdb_file",
                            -format => 'PDB');

my $struc = $structio->next_structure;
for my $chain ($struc->get_chains) {
    for my $res ($struc->get_residues($chain)) {
        for my $atom ($struc->get_atoms($res)) {
            print join " ",$atom->xyz,"\n" if $atom->pdb_atomname eq " CA ";        
        }
    }
}

で、ベンチマーク

$ time python test.py
real    0m1.161s
user    0m0.996s
sys     0m0.116s

$ time perl pdbtest.pl
real    0m3.183s
user    0m3.056s
sys     0m0.044s

平均とってないけど、何回か実行してみてもpythonのほうがbioperlよりも3倍くらい速かった。bioperlのコードってなんだかなと思うことがままある。pdb_atomnameなんかも4文字で前後にスペース入ってるし。というわけで、SBDD周りのプログラミングはbiopythonのほうが扱いやすい感じがしてる。

ProductName みんなのPython
柴田 淳
ソフトバンククリエイティブ / ?円 ( 2006-08-22 )


余談だが、Turbogears普通に触れる程度までpython覚えてやる(意地でも)とか思ったので、Dive Into Pythonも読み中。