« 風呂釜壊れた日記 |Main| 花粉症日記 »

« 風呂釜壊れた日記 | zakki(雑記) | 花粉症日記 »

Python Developer's camp 日記

さて、とりあえず上野に行こう。

上野に着いた。

東京に来てからというもの、 ことあるごとに頭の中で曲がなる。 「♪JR新宿駅の東口を出たら~」とか。

「♪上野発の夜行列車降りたときから」ってのは 乗って降りてるから上野の歌ではないなぁ。 どこの歌なんだろう。

上野から新幹線が出ているとは知らなかった。 今まで僕にとって新幹線ってのは博多から東京まで運転しているものなので。

長野に着いた。

牛に轢かれて善光寺

長野電鉄。 ちょうど目的地行きの特急があった。 特急券は100円。リーズナブル。

P1060937
P1060937 posted by (C)にしお

全然雪が積もってないなぁ。 箱根登山鉄道みたいに山に登るのかと思ったら、 平らなところを走っている。 後で登るのかな。

箱根と長野の位置関係を後で調べよう。 たぶん長野の方が北だとは思うけど、 どちらが東なのかよくわからない。

千曲川。

もうすぐ終点って言われたのにまだ平らだ。

あ、ここから急勾配を登るんだって。

酔いそう。

湯田中の駅に着きました。 雪がありません。

P1060946
P1060946 posted by (C)にしお

あ、ここからバスに乗るんだった。

時刻表…の写真を撮ったつもりだったのに取れていなかった。

現在時刻は13時8分。うわっ、ラストのバスがもうすぐだ。 あと10分遅れてきていたらタクシーで行くはめになったかも。

登ったら雪がたくさんあった。

持ってきたSOYJOYがパンパンにふくれた。

P1060951
P1060951 posted by (C)にしお

サルが来たら捕まえてPythonを教えて 本物の「サルでもわかるPython」を作る計画。

だんだんにぎわって参りました。


= 20時。 僕のマシンが無線LANにつながらない。 PHSもつながりにくい。 Lingrが切れて再接続の繰り返しで全然発言できない。

Lingrに入っていると、回線状況が悪化したときにb-mobileの接続ダイアログが出てきて、 きっとプレゼンの邪魔になるので退室。

djangobook.com

13行でWordPressもどきができちゃう。

Jythonの発表終了。

無線LANをONにした状態でサスペンドすると、 再起動するまで無線LANがつながらなくなるような気が。

>>> from pprint import pprint
>>> pprint(vars(__builtins__))

import pdb;pdb.set_trace()

enthoughtにcoverageってライブラリがあって、便利らしい。

>>> import dis
>>> def foo(e):
	return e + 1

>>> dis.dis(foo)
  2           0 LOAD_FAST                0 (e)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD          
              7 RETURN_VALUE        

= Pythonで
# spam.py
import spam
をパスの通ったところにおいて、import spamすると spam.spam.spam…と無限にいける。
= 2日目。 初日は喉が痛かったが、 少し腫れてきた。 そして左の鼻の奥だけが痛い。 鼻水が止まらない。
= 僕の講義資料は Jython インタラクティブ・ハッキング クラスなんていらないさ! に置きました
= みんながTodoListを作っているから、 僕もネタとしてワンライナーで作ろうかと思ったけども、 設計しているうちにまともに作りたくなってしまった。

優先度はなし。デッドラインはNoneもOK。 重要なフィールドはrelyOnで、 Todoが別のTodoに依存しているかどうかを記述できる。 Todoはデッドラインが近いほど優先度が高く、 多くの優先度の高いTodoがrelyOnしているTodoは優先度が高くなる。

relyOnは推移律を満たさないといけないけど、 それを弱めたような「タスクAをやってからのほうがタスクBが楽にorいいクオリティでできるかも」 という関係を入れても面白いかも知れない。 で、循環参照が起きても構わないようにして、 最終的にどれの優先度が高いかはGoogle PageRank的なアルゴリズムで決める。


= ライトニングトーク。 スケッチブックメソッド。 逆に新しい。
= いろいろ勉強になった。 4月になったらDjangoを勉強しようかと思っていたけど、 Ploneをいじってみたい気もしてきた。

typoで動かなかったときに、typoそうなところを見つけてくれるプログラムがあると便利なのでは。 re.findall("[_\w][_\w\d]*", data)した後で、よく似ているペアをtypo候補として提示する。


= そうか。遅延評価か。

モードを指定しないでも、呼んだメソッドによって適当な方法で開いてくれるファイルオブジェクト。

>>> class myfile(object):
	def __init__(self, filename):
		self.filename = filename
		self.file = None
	def _ensure_opened(self, mode):
		if not self.file:
			self.file = file(self.filename, mode)
	def write(self, s):
		self._ensure_opened("w")
		self.file.write(s)
	def read(self):
		self._ensure_opened("r")
		return self.file.read()
	def close(self):
		self.file.close()

		
>>> f = myfile(r"c:\hoge.txt")
>>> f.write("Hello!")
>>> f.close()
>>> f = myfile(r"c:\hoge.txt")
>>> f.read()
'Hello!'
>>> f.close()

= 上のようにした場合はreadlineとかを引き継ぐのが面倒。
>>> class myfile(object):
	def __init__(self, filename):
		self.filename = filename
		self.file = None
		def bind(name, mode = None):
			def foo(*args, **kw):
				f = self._get_opened_file(mode)
				method = f.__getattribute__(name)
				return method(*args, **kw)
			self.__dict__[name] = foo
		bind("write", "w")
		bind("read", "r")
		bind("readlines", "r")
		bind("close")
			
	def _get_opened_file(self, mode = None):
		if not self.file:
			self.file = file(self.filename, mode)
		return self.file

	
>>> f = myfile(r"c:\hoge.txt")
>>> f.write("Hello!")
>>> f.write("Hello!2")
>>> f.close()
>>> f = myfile(r"c:\hoge.txt")
>>> print f.read()
Hello!Hello!2
>>> f.close()
こういう「ほとんどのメソッドを書き換える必要がある」ケースならば、 「親クラスのメソッドを変更しないで引き継ぐことができる」継承を使ってもメリットがほとんどない。
class myfile(object):
	def __init__(self, filename):
		self.filename = filename
		self.file = None
		def bind(name, mode = None):
			def foo(*args, **kw):
				f = self._get_opened_file(mode)
				method = f.__getattribute__(name)
				return method(*args, **kw)
			self.__dict__[name] = foo
			
		for name in dir(file):
			if name.startswith("write"):
				bind(name, "w")
			elif name.startswith("read"):
				bind(name, "r")
			else:
				bind(name)
			
	def _get_opened_file(self, mode = None):
		if not self.file:
			self.file = file(self.filename, mode)
		return self.file

>>> f = myfile(r"c:\hoge.txt")
>>> f.write("Hoo\n")
>>> f.write("Foo")
>>> f.close()
>>> f = myfile(r"c:\hoge.txt")
>>> f.readlines()
['Hoo\n', 'Foo']
>>> f.close()
こういう「決まったパターンでメソッドを書き換える」というケースだと、 やっぱり上みたいにアスペクト指向的なアプローチをするのが楽。
= MercurialHG
= 帰ってきた。なんだかどっと疲れた。 鼻水が止まらないし。
= Gopher: missingpy
MissingPy is a Haskell binding to Python and library of Python interfaces for Haskell.

これを使えばHaskellでPythonのライブラリが使えるのかな。

MissingPy permits you to call Python code from Haskell. It does NOT permit you to call Haskell code from Python.
逆は無理らしい。
= typoチェッカー。 レーベンシュタイン距離 - Wikipedia を使って、二つの単語の距離を決める。
>>> def calcLevenshteinDistance(s1, s2):
	SKIP_COST = 1
	DIFF_COST = 1
	class MyMat:
		def __init__(self):
			self.value = {}
		def get(self, i, j):
			if i == -1:
				return (j + 1) * SKIP_COST
			elif j == -1:
				return (i + 1) * SKIP_COST
			else:
				return self.value[i][j]
		def set(self, i, j, value):
			if not self.value.has_key(i):
				self.value[i] = {}
			self.value[i][j] = value

	mat = MyMat()
	l1 = len(s1)
	l2 = len(s2)
	for (i, c1) in enumerate(s1):
		for (j, c2) in enumerate(s2):
			cost = 0
			if c1 != c2: cost = DIFF_COST
			mat.set(i, j, min(
				mat.get(i - 1, j - 1) + cost,
				mat.get(i, j - 1) + SKIP_COST,
				mat.get(i - 1, j) + SKIP_COST))
	return mat.get(l1 - 1, l2 - 1)

>>> calcLevenshteinDistance("Hello", "Hollo")
1
>>> calcLevenshteinDistance("Hello", "Hello")
0
>>> calcLevenshteinDistance("Hello", "Helo")
1
で、こんな感じで似ている順に表示してみる。
>>> def typoChecker(data):
	import re, sets
	THRESHOLD = 0.75
	candidate = []
	words = list(sets.Set(re.findall("[_\w][\_\d\w]*", data)))
	for (i, w1) in enumerate(words):
		for w2 in words[i + 1:]:
			d = calcLevenshteinDistance(w1, w2)
			l = len(w1) + len(w2)
			s = float(l - d) / l
			if THRESHOLD < s:
				candidate.append((s, w1, w2))
	candidate.sort(reverse = True)
	for c in candidate: print c
入力するデータはこんなもの。さてどこがtypoでしょう。
>>> data = """
class myfile(object):
	def __init__(self, filename):
		self.filename = filename
		self.file = None
		def bind(name, mode = None):
			def foo(*args, **kw):
				f = self._get_opened_file(mode)
				method = f.__getattribute__(mame)
				return method(*args, **kw)
			self.__dict__[name] = foo
			
		for name in dir(file):
			if name.startswith("write"):
				bind(name, "w")
			elif name.startwith("read"):
				bind(name, "r")
			else:
				bind(name)
			
	def _get_opened_file(self, mode = None):
		if not self.file:
			self.file = file(self.filename, mode)
		return self.file

"""
出力結果は下記。
>>> typoChecker(data)
(0.94736842105263153, 'startwith', 'startswith')
(0.875, 'mame', 'name')
(0.83333333333333337, 'for', 'foo')
(0.8125, '__dict__', '__init__')
(0.80000000000000004, 'file', 'myfile')

= 帰りは柴田さんの車に乗せてもらいました。 執筆はマラソン。

トラックバック(Trackback)

Trackback URL: http://www.nishiohirokazu.org/mt/mt-tb.cgi/524

フィードバック

by おびなた | 2007年03月04日 22:55

「♪上野発の夜行列車降りたときから」は津軽海峡冬景色の冒頭句。「青森駅は雪の中」と続くので、舞台は青森駅かな。 Python Developer's Campの会場って、志賀高原の高天が原でしたよね。長野駅から同じ長野電鉄の高速バス一本で行けるんだけど、それは使わなかったのね。

プロシンの会場みたいなのをイメージしていたので、駅に着いた後のバスが長くて乗り換えまであるとは思わなかったのでした。

ご意見・ご感想をお送りください(フィードバック)

(フィードバックはメールで送信され、基本的に表示されませんが、内容によっては公開させていただくこともございます。ご了承ください。Your comment doesn't appear the page immediately. If the comment has value to other people, it will be put on the page or subsequent entries. Thank you.)

上の情報は、いずれも未記入でかまいません。 All of above questions are optional.