fc2ブログ

【Python】動的ディスパッチと動的メソッド定義

2012-03-23 00:29:58 Fri

パイソニアな人にはもはや今更のことですが、JavaのReflectionみたいなことを。

まあ、先人の知恵を借りれば何も語ることはないのですが。

http://d.hatena.ne.jp/yuheiomori0718/20120116/1326715412
http://d.hatena.ne.jp/littlefive/20110419/1303210605

とりあえず咀嚼したことを。

■動的ディスパッチ



obj = "abc" # objはstrオブジェクトであるtype(obj)とかで

getattr(obj, 'upper')() # strクラスのupperメソッドを実行している



まあコメントそのままです。

■動的メソッド定義



colours = {"black": "000",
"red": "f00",
"green": "0f0",
"yellow": "ff0",
"blue": "00f",
"magenta": "f0f",
"cyan": "0ff",
"white": "fff"}

class MyString(str):
pass

for name, code in colours.iteritems():
def _in_colour(self, code=code): # 連想配列を繰り返してメソッドを定義し続ける。このstatementでcodeにデフォルト値を代入している
return '%s' % (code, self)
setattr(MyString, "in_" + name, _in_colour) # ここでMyString型にメソッドを動的に追加している。メソッド名は文字列。

print MyString("Hello, world!").in_blue() # 動的に拡張されたMyStringのメソッドを実行。



プロトタイプチェーンとか暗黙参照とか気にせずに言えばjavascriptのprototypeみたいなもんか。

オブジェクトに対してメソッドを動的に追加しているのではなく、クラスに対して追加している、っていう感じか。

いやー、どの言語もこういう文字列遊びって楽しいなー。


【Python】関数の引数について

2012-03-23 00:13:48 Fri

パイソニストには当たり前のことですが、関数がとる引数のアスタリスクについてメモ。

あ、どうでもいいことですが、2012/03/23 現在、
IntellijIDEAのプラグインでpythonとrubyってpythonの2倍近くrubyがDLされていてびっくりしました。
rubyが10万DL、pythonが5万とかでした。
pythonの方がpydevなどIDEが多いからなのかそれとも…と色々邪推してしまいました。
というのは置いといて…。


下記の先人の知恵を借りれればたいていわかります。

http://jutememo.blogspot.jp/2008/09/python_13.html
http://d.hatena.ne.jp/eth0jp/20100219/1266526197
http://www.daisaru11.jp/blog/python-%E3%83%A1%E3%83%A2/%E9%96%A2%E6%95%B0%E5%BC%95%E6%95%B0%E3%81%AE%E5%8F%97%E3%81%91%E6%B8%A1%E3%81%97/

簡単に。


def hoge(*args):
pass

hoge(1,2,3,4,5,6,7,8,9,'a','b','c')



アスタリスク1つはタプルとして可変長引数を受け取るという意味。


def hoge(**args):
pass

hoge(a=1,b=2,c=3)



アスタリスク2つはdictionaryとして可変長引数を受け取るという意味。


def hoge(*args, **dict):
pass

hoge(1,2,3,4,5,6,7,8,9,'a','b','c',a=1,b=2,c=3)



こういう引数の場合は、1~cまでがargsに、{a:1,b:2,c:3}がdictに代入されて関数が実行されます。


def hoge(*args, **dict):
pass

hoge(1,2,3,4,5,6,7,8,9,'a','b','c',a=1,b=2,c=3,0,10,11,12,'d')



じゃあこれはどうなるかというと


SyntaxError: non-keyword arg after keyword arg



になります。

そりゃまあ仕方ない。

a=1のような keyword arg(キーワード引数)の後にnon-keyword arg(ノンキーワード引数)を指定することはできない言語仕様だからのようです。

そりゃそっか。

あ、先人様がおまけで書いてくれていましたが、zipメソッド便利~。


a = (1, 2, 3)
b = (4, 5, 6)
zipped = zip(a,b)
print zipped #[(1, 4), (2, 5), (3, 6)]

a2, b2 = zip(*zipped)
print a2 #(1, 2, 3)
print b2 #(4, 5, 6)



【Python】py2exeエラーだらけ

2012-02-19 16:20:08 Sun


C:\TracLight\python\python.exe C:/Users/isann/IdeaProjects/proto_freezen/src/setup.py py2exe
C:\TracLight\python\lib\site-packages\py2exe\build_exe.py:16: DeprecationWarning: the sets module is deprecated
import sets
running py2exe
*** searching for required modules ***
*** parsing results ***
*** finding dlls needed ***
Traceback (most recent call last):
File "C:/Users/isann/IdeaProjects/proto_freezen/src/setup.py", line 14, in
zipfile = None)
File "C:\TracLight\python\Lib\distutils\core.py", line 152, in setup
dist.run_commands()
File "C:\TracLight\python\Lib\distutils\dist.py", line 975, in run_commands
self.run_command(cmd)
File "C:\TracLight\python\Lib\distutils\dist.py", line 995, in run_command
cmd_obj.run()
File "C:\TracLight\python\lib\site-packages\py2exe\build_exe.py", line 243, in run
self._run()
File "C:\TracLight\python\lib\site-packages\py2exe\build_exe.py", line 306, in _run
self.plat_finalize(mf.modules, py_files, extensions, dlls)
File "C:\TracLight\python\lib\site-packages\py2exe\build_exe.py", line 1157, in plat_finalize
import pythoncom
File "C:\TracLight\python\lib\site-packages\pythoncom.py", line 3, in
pywintypes.__import_pywin32_system_module__("pythoncom", globals())
File "C:\TracLight\python\lib\site-packages\win32\lib\pywintypes.py", line 98, in __import_pywin32_system_module__
raise ImportError("No system module '%s' (%s)" % (modname, filename))
ImportError: No system module 'pythoncom' (pythoncom26.dll)

Process finished with exit code 1


原因は、、、単純でした。

WS000226.jpg

pythoncom26.dllが見つからないと。

じゃあほんとにないのかと。

探してみます。

WS000227.jpg

あるじゃない!

パスが違いますね。

じゃあ適当に「C:\TracLight\python\pythoncom26.dll」にコピペ。

で、実行したら正常完了。

よしよし。


【Python】py2exeのインストール

2012-02-19 16:02:52 Sun

由緒正しいパイソニアのみなさまは、
Traclightなんて使わずにちゃんとpythonインストーラーからインストールしてますよね。

僕はGUI世代のゆとりなので、Traclightからpython2.6をインストールしていました。

で、2.5じゃなくこっちの2.6にpy2exeをインストールしたかったのですが、手こずりました。

というのも、py2exeインストーラーはレジストリを読んでpythonインタプリタプログラムのパスを決めてて、
任意で変更できませんでした。

なのでレジストリをちょいと触ってやる必要がありました。

すなおにpythonインストーラーからインストールしておけば、
こんな苦労はしないと思います。

この界隈は、詳しくないならば標準に従うべき、ですよね、トホホ。


1.レジストリの何をみてるのかを調査

これは、process monitorで調べました。


Process Monitor はプロセスが行った処理 (ファイル システム、レジストリ、プロセスおよびスレッドの活動) をリアルタイムで表示するツールです。そのため、 Process Monitor はシステムのトラブルシューティングやマルウェア検出などに役立てることができます。


だそうです。

py2exeインストーラーを起動してタスクマネージャーからPIDを参照しておきます。

で、process monitorでPIDからfilterをしてプロセスを絞り込みます。

次にpy2exeで該当のレジストリを探しているだろうところまでウィザードを進めて
直近のログを参照します。

WS000216.jpg

おそらく「HKLM\SOFTWARE\Python\PythonCore」あたりを見てるのだろう、と推測します。

2.値を探してみる

regeditを起動して「HKEY_LOCAL_MACHINE」あたりから上記のパスへ移動していきます。

WS000218.jpg

それっぽいのがありました。

※2.6系は2.5を参照しながら自力で作成した階層です。

2.5を参照しつつ2.6を作成します。

ただし、完全コピーじゃなく、2.6の任意のパス、
TracLight使っているなら「C:\TracLight\python」あたりをですね、適当に値にします。

キー : 「HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6\InstallPath」
値 : C:\TracLight\python

キー :「HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6\InstallPath\InstallGroup」
値: Python 2.6

キー : 「HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6\PythonPath」
値 : C:\TracLight\python\Lib;C:\TracLight\python\DLLs;C:\TracLight\python\Lib\lib-tk


くらいをちゃんと書いておけばいいかもですね。

私はこれと2.5と同じキーを作成しました。


3.IDEでimportしてみる

WS000219.jpg

WS000220.jpg

とりあえずここまではOKということで。
あとはpy2exeを試してみる、ということで。


【Python】テンプレートエンジンjinja2を使ってみる

2012-02-16 00:59:13 Thu

■jinja2を使ってみる


pythonでテンプレートエンジン、というといくつもあるみたいです。

http://labs.unoh.net/2007/05/python_1.html
http://d.hatena.ne.jp/ymotongpoo/20101213/1292252414


  • Cheetah

  • Mako

  • Jinja2

  • Django

  • Kid

  • Genshi

  • Clearsilver

  • Nevow

  • SimpleTAL

  • Chameleon

  • web2py

  • Tornado

  • Bottle



で、大御所がおすすめされていたのでjinja2を使ってみました。


■とりあえず動かす


ひとまず動かしてみます。
easy_install jinja2 でライブラリをインストールしておきます。


from jinja2.environment import Environment
from jinja2.loaders import FileSystemLoader

env = Environment(loader=FileSystemLoader('../templates/'))
template = env.get_template('template.txt')
data_maps = {'name':'jinja'}
file = open('../dest/test.txt', 'w+')
file.write(template.render(data_maps))

templatesディレクトリにある「template.txt」ファイルを元にして
destディレクトリに「test.txt」ファイルを出力します。

Loaderには色々あるようで、場面に合わせて最適なローダーを使うようにします。
http://www.geocities.jp/showa_yojyo/note/python-jinja2.html#environment

今回は「FileSystemLoader」を使ってます。

テンプレートには「name='jinja', hoge='fuga'...」で値を渡します。
dictionaryだと楽かもですね。


出力 : {{name}}

条件分岐 :
{% if name != '' %}
{{name}}
{% else %}
空でした
{% endif %}

繰り返し :
{% for item in items %}
{{ loop.index0 }}
{% endfor %}



ざっとでした。

参考URL
http://ymotongpoo.appspot.com/jinja2_ja/api.html
http://www.geocities.jp/showa_yojyo/note/python-jinja2.html
http://nayuta.info/archives/67
http://www.gesource.jp/weblog/?p=3527

名言集
全記事(数)表示
全タイトルを表示
ブログ内検索
Loading