« 2007年09月 | メイン | 2007年11月 »

2007年10月 アーカイブ

2007年10月16日

Pythonの辞書をドットでアクセス

Pythonの「辞書」はとても便利なデータ構造ですが、「x」というキーに関連づけられている値を取り出すのには「['x']」とキー以外に4文字も書かなければ行けなくて面倒です。
>>> p = dict(x=1, y=2)
>>> p
{'y': 2, 'x': 1}
>>> p['x']
1
JavaScriptみたいにp.xでアクセスできると便利です。 そこでp.xでアクセスできるようにする関数を作りました。
>>> p = modulize(p)
>>> p.x
1
実装はこちら:
>>> def modulize(dictionary):
	import imp
	m = imp.new_module("")
	m.__dict__.update(dictionary)
	return m
なお、modulizeの時点で辞書がコピーされているので、modulize済みのオブジェクトのメンバを書き換えても元の辞書は変化しません。
>>> p = dict(x=1, y=2)
>>> p2 = modulize(p)
>>> p2.x = 100
>>> p
{'y': 2, 'x': 1}
変更済みの辞書を取得するには下のように__dict__を使います…ってモジュールにしたせいで__doc__とかが勝手に追加されていますね…
>>> p2.__dict__
{'y': 2, '__name__': '', '__doc__': None, 'x': 100}
…すなおに下のように書いた方がいいかも。
>>> class MyDict(dict):
	__getattr__ = dict.__getitem__
	__setattr__ = dict.__setitem__
	__delattr__ = dict.__delitem__

	
>>> MyDict()
{}
>>> d = _
>>> d.x = 1
>>> d
{'x': 1}
>>> d.x
1
>>> del d.x
>>> d
{}

2007年10月17日

Pythonで関数名を安全に変更する

Pythonのような動的な言語では、Javaのように「メソッドの名前を呼び出しも含めて変更」というリファクタリングが簡単ではありません。整合性をチェックするフェーズがないので、不用意に名前を変更すると実行時に「そんな名前の関数はない」と怒られてしまいます。

そこで「一度deprecated(非推奨)にする」という方法を考えました。

まず下のようにfooという関数と、それを読んでいるcallerという関数を作りました。今からこのfooをbarという名前に変更したいと思います。 しかし、実際にはcallerは大量のソースの中に散らばっているものとします。

>>> def foo():
	return 1

>>> def caller():
	return foo()

fooの名前を変更します。ここではbar = fooとしていますが、もちろんdef foo...をdef bar...に書き換えるのでもOKです。実際は後者になるでしょう。 そして、fooという名前で改めて警告メッセージを出してbarを呼ぶ関数を定義します。
>>> bar = foo
>>> def foo():
	import inspect
	print "'foo' is deprecated: called from", inspect.stack()[1][3]
	return bar()
こうすると、うっかりcallerの中のfooの呼び出しをbarの呼び出しに変え忘れても:
>>> caller()
'foo' is deprecated: called from caller
1
変える値は変わらず、警告メッセージだけが表示されるようになります。警告は今はprintで出していますが、ログに出すなりなんなりするといいと思います。
追記: 毎回こういうことを書くのも面倒なので関数にまとめました。
>>> def deprecated(f):
	def deprecated_func(*args, **kw):
		import inspect
		print "'%s' is deprecated:" % f.func_name,
		print "line %s in '%s'" % tuple(inspect.stack()[1][2:4])
		return f(*args, **kw)
	return deprecated_func

>>> def nibai(x):
	return x * 2

>>> def foo():
	print nibai(10)
	print nibai(20)

	
>>> foo()
20
40
>>> nibai = deprecated(nibai)
>>> foo()
'nibai' is deprecated: line 2 in 'foo'
20
'nibai' is deprecated: line 3 in 'foo'
40

2007年10月29日

「どう書く?org」(ベータ版)を公開しました

どう書く?orgというサービスを公開しました。

どう書くorgについてオフィシャルに言及するのは初めてなのですが、 アルファ版の時点ではてなブックマークのホットエントリーになったり、 オレンジニュースやじうまWatchで言及していただいたりしたので すでにご存じの方もいらっしゃるかもしれません。 そこでこの記事では今まで語ってこなかった「どうして『どう書くorg』を作ろうと考えたのか」について解説したいと思います。

そもそものきっかけはマルチリンガルなシソーラス検索 - rubyco(るびこ)の日記でした。 言語Xを使っている人が新たに言語Yを使うときになにが障害になるか、というと、 やはり「言語Xでならどうやるか0.1秒で思いつくような簡単な内容を、 言語Yではドキュメントをひっかきまわして探さないといけない」というフラストレーションなわけです。 そのフラストレーションを避ける気持ちが、プログラマを「自分が一番慣れている言語」という檻に閉じこめるのです。 プログラミング言語間の対訳があれば、殻を破ってマルチリンガルの大空に羽ばたくことができるのに。

さて、この対訳マルチリンガル・クックブックを作る上で、 まずは「Wikipedia的なアプローチで言語間の対訳データが集められないか」 と考えPukiWikiで集積サイトを作りました。 しかし「これは絶対に盛り上がらない」と判断して公開しませんでした。 単なるWikiではコードを書いてもらうインセンティブに欠けると思いました。

その後、どういう流れがあったのかは正確には覚えていません。しかし、いつしか キミならどう書く 2.0 - ROUND 1 - Lightweight Language Ring のようなアプローチをもったいないと感じるようになりました。 お題に対してコードを書いている人のほとんどは、そのコードの再利用を禁止したいとは思っていないはずです。 なのに、許可を明示的に取らないせいで実質的に再利用できずに散逸させてしまっています。 せっかく無償でいろいろな言語のコードを書いてもらうことができているのに。これはとてももったいないことです。

このようにして「どう書くorg」の三本柱「マルチリンガル志向」「お題にチャレンジ」「再利用可能なライセンス」ができました。 みなさんのおかげで、7月頭にどう書くorgを公開してから今までの4ヶ月弱で、2796件のコードが投稿されています。 1日平均20件以上という計算になります。

今後の課題は、こうやって集まったコードをどう加工するかだと思います。 指定したコード中から特定の文字列を検索して、同じお題の別の言語のコードを表示する機能 を3ヶ月も前に実装したのですが、これは現状の「お題と解答」というシステムではコードの粒度が大きすぎてなかなか望み通りのものが得られません。 ソースコードを静的に解析することで使われているモジュールを推定する機能(どう書く?org Python 使用モジュール一覧) がついたので、次は「同じお題で使われることの多いモジュールは似た機能のモジュール」というような推定でしょうか。 それとも、お題にするには粒度が小さすぎるような内容を 文字列中のアルファベットを大文字にする どう書く?org のような公開トピックとしてどんどん作ることで粒度の小さいコードを増やすのがいいのでしょうか? まだまだ先が見えません。

しかし、たとえどう書くorgプロジェクトが道半ばで頓挫しても、 集まった「自由に再利用できる」コードは他のプロジェクトの肥やしになるはずです。 進めるところまで進んでみるのが正解かな、と思っています。

長々と昔話や妄想を書きつづってきましたが、まとめたいと思います。 どう書くorgは今まで「出されたお題をいかに解くか競い合う、プログラマのためのコロシアム」と名乗っていました。しかし「プログラマのためのコロシアム」なのは手段であって目的ではありません。どう書くorgの目的は「マルチリンガル・クックブック」を自然発生させることなのです。

About 2007年10月

2007年10月にブログ「西尾泰和のブログ @ Cybozu Labs」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2007年09月です。

次のアーカイブは2007年11月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。