pythonで引数渡すとき

昨日よくわからなかったので

d = [2007, 8, 1]
datetime.date(d[0], d[1], d[2])

と書いたのだけど

datetime.date(*d)

でいいのね。

SQLObjectとmatplotlibで血圧管理

前週末から風邪がひどくて、会社を休んで寝ている。今日は多少ボーっとするけど昨日よりはずっと楽なので蒲団の中でノートパソコンと戯れたり。で、この前の血圧管理のグラフ化をやってみた。はてなのグラフを二つ重ねるというのは僕も考えたんだけど、CUIから

mybp -b 142,88

とか

mybp -b 142,88 -d 2007-07-31

とタイプするだけのほうがなんとなく長続きしそうだし(今までの経験から)。とここまでエントリを書いたところで、はてなグラフでそんなのやってるの思い出した

むむーですよ。ま、pythonで書きたかった+綺麗なグラフが好きだった、、、ということで、書いたのはココ

O/RマッパはSQLObjectで。クラスを定義したら、

class BloodPressure(SQLObject):
    sbp = IntCol()
    dbp = IntCol()
    date = DateCol(default=datetime.date.today(), unique = True)

createTableメソッド呼ぶ

BloodPressure.createTable()

これで、実際にテーブルつくってくれるのでSQL文考えなくてよいし、テーブル作り直したいときにもdb消してもう一度createTableメソッド呼べばいいので心理的にも楽。

matplotlibは昨日書いたのを。データが少ないと目盛りがおかしいけど、1週間も続ければきちんとなるでしょう。

血圧

それにしても僕の血圧やたら高いなぁ。困った困った。

あとoptparseで固定引数の処理の仕方がよくわからなかったのだけど、パスワード生成スクリプトをきっかけにoptparseを使ってみましたを眺めたら解決した。

(options, args) = parser.parse_args()

ここのargsに固定引数が入ってんのね。

matplotlibを使う

pythonのグラフ描画ライブラリであるmatplotlibで日付ごとにプロットするサンプル。

from pylab import *
from matplotlib.dates import MONDAY, WeekdayLocator
import datetime

start_date = datetime.date(2007, 5, 1)
end_date   = datetime.date.today()
delta = datetime.timedelta(days=1)

mondays   = WeekdayLocator(MONDAY)

dates = drange(start_date,end_date,delta)

s = rand(len(dates)) + 85
t = rand(len(dates)) + 80

fig = figure()
ax = fig.add_subplot(111)
ax.plot_date(dates, s, 'r--')
ax.plot_date(dates, t, 'bo-')

ax.xaxis.set_major_locator(mondays)
ax.autoscale_view()
ax.grid(True)
fig.autofmt_xdate()

title('My Blood Pressure')
xlabel('Date')
ylabel('Blood Pressure')

fig.savefig('datetest')

matplotlib

matplotlibのimportエラー

matplotlibを0.91.1にあげたら

NameError: name 'gtk' is not defined

とかでて動かなくなった。仕方ないのでsvnのrev4730を入れたら動いたけど、それでも

  libpng: 1.2.22
 Tkinter: Tkinter: 50704, Tk: 8.4, Tcl: 8.4
wxPython: 2.8.4.0
         * WxAgg extension not required for wxPython >= 2.8
    Gtk+: no
         * pygtk present but import failed
      Qt: Qt: 3.3.8, PyQt: 3.17.3
     Qt4: no
   Cairo: 1.4.0

となっている。pygtkは入ってんのになー

PythonでWu-Manber

ProductName Mastering Algorithms With Perl
Jon Orwant,Jarkko Hietaniemi,John MacDonald
Oreilly & Associates Inc / ¥ 3,263 ()
在庫あり。

ビット演算を利用したアルゴリズム。Shift-ADDと違いdifference,insertion,deletionを考慮する。

可能性を論理和として積み上げていってShift-ORみたいなアプローチで評価するとこだと思う。いまいちちゃんと理解できてないが。

   for j in range(1,k+1):
       s[j]  = (r[j] << 1) & Tc
       s[j] |= (r[j-1] | s[j-1]) << 1
       s[j] |= r[j-1]
       s[j] |= 1

あと、perlで@a = @bとやれるところがpythonではa=bとできず、 b = copy.copy(a)なのね。

#!/usr/bin/env python

import copy

def amatch (T,P,k=-1):

   text_length = len(T)
   pattern_length = len(P)
   po2 = map(lambda(x): 1 << x,range(31))

   if k == -1: k = int(pattern_length/10) + 1

   Table = [0] * 256
   for i in range(pattern_length):
       Table[ord(P[i])] |= po2[i]

   r = [0] * (k+1)
   for i in range(1,k+1):
       r[i] = r[i-1] | po2[i-1]

   mb = po2[pattern_length-1]

   s = [0] * (k+1)
   for i in range(text_length):
       s[0] <<= 1
       s[0] |= 1
       Tc = Table[ord(T[i])]
       s[0] &= Tc

       for j in range(1,k+1):
           s[j]  = (r[j] << 1) & Tc
           s[j] |= (r[j-1] | s[j-1]) << 1
           s[j] |= r[j-1]
           s[j] |= 1

       if s[k] & mb:
           return i - pattern_length + 1 if i > pattern_length else 0
       r = copy.copy(s)
   return -1

if __name__ == '__main__':
   print "match: ", amatch("pearl","perl",1)

PythonでShift-ADD

ProductName Mastering Algorithms With Perl
Jon Orwant,Jarkko Hietaniemi,John MacDonald
Oreilly & Associates Inc / ¥ 3,263 ()
在庫あり。

これもビット演算を利用したアルゴリズム。differenceを許容するけどinsertion,deletionは駄目。

#!/usr/bin/env python

from math import *

def shift_ADD (T, P, k=-1):
   text_length = len(T)
   pattern_length = len(P)

   if k == -1: k = int(log(text_length)+1)
   if k == 0:  return T.find(P)
   if pattern_length == 1: return T.find(P)
   if pattern_length > text_length: return -1
   if pattern_length == text_length and P == T: return 0

   bits = int(log(k+1,2)) + 1 # ????
   mask = 1 << ( bits - 1 )
   ovmask = 0

   for i in range(pattern_length):
       ovmask |= mask
       mask <<= bits

   table = [ovmask >> (bits-1)] * 256

   nmask = 1
   for i in range(pattern_length):
       table[ord(P[i])] &= ~nmask
       nmask <<= bits

   mask = ( 1 << ( pattern_length * bits )) -1
   state = mask & ~ovmask
   ov = ovmask
   watch = ( k + 1 ) << ( bits  * ( pattern_length - 1 ) )

   for i in range(text_length):
       state = ((state << bits) + table[ord(T[i])]) & mask
       ov    = ((ov << bits) | (state & ovmask))    & mask
       state &= ~ovmask
       if (state | ov) < watch:
           return i - pattern_length + 1

   return -1

if __name__ == '__main__':
   print shift_ADD("perlpethonxx","python",2)

pythonで2進数表記はどうやんの

int("101111",2)とかやると2進数の表現を10進数にできるということが分かったんだけど、逆に10進数で47を与えられたら101111といった2進数表現にするやり方がわからなかった。

Shift-ORのコード書いてるときに15って01111だよな~、5って00101だっけ?とか脳内変換はちょっと疲れた。4 | 1とか7 & 4とかいう脳内ビット計算も疲れる。

PythonでShift-OR

ProductName Mastering Algorithms With Perl
Jon Orwant,Jarkko Hietaniemi,John MacDonald
Oreilly & Associates Inc / ¥ 3,263 ()
在庫あり。

Shift-ORってのはshiftしてORとって、どんどこどんどこと0を左送りにしていって最後まで0送りできた場合にパターンマッチ成功。最後がマッチしたかどうかは補数(一番左が0で残りが1)のANDをとって0が帰ってくるかどうかで判断するという文字列検索アルゴリズム。

#!/usr/bin/env python

def shift_OR_exact (T,P):

   text_length = len(T)
   pattern_length = len(P)

   if pattern_length > text_length: return -1
   if pattern_length == text_length: return 0
   if pattern_length == 1: return T.find(P)

   m1b = (1 << pattern_length ) -1
   table = [m1b] * 256

   mask = 1
   for i in range(pattern_length):
       table[ord(P[i])] &= ~mask
       mask <<= 1

   watch = 1 << ( pattern_length - 1 )

   for i in range(text_length):
       i = T.find(P[0],i)
       if i == -1: return -1

       state = m1b

       while i < text_length:
           state = ( state << 1 ) | table[ord(T[i])]
           if ( state & watch ) == 0:
               return i - pattern_length + 1

           if state == m1b: break
           i += 1

   return -1

if __name__ == '__main__':
   print shift_OR_exact("perlpypythonruby","python")
  • ビット演算はperlもpythonも似た感じ
  • perlのindexはpythonのfind(こっちは組み込みのメソッド)

iKnowの日々の記録をグラフに綴る

iKnow の進捗を Python で取得するというエントリをみつけたので、さらにmatplotlibでグラフ書くようにしてみた。これを一日の終わりにcronで実行すれば記録できる。

#!/usr/bin/env python

import urllib
from BeautifulSoup import BeautifulSoup
import re
from sqlobject import *
from pylab import *
from matplotlib.dates import MONDAY, WeekdayLocator
import datetime,os

# --- Configure --- #
mydb = '/home/kzfm/iknow.db'
mygraph = '/var/www/html/images/lf/iknow'
myname = 'kzfm'

myconnect = 'sqlite://' + mydb
sqlhub.processConnection = connectionForURI(myconnect)

class RecKnow(SQLObject):
    iknow_study = IntCol()
    iknow_finish = IntCol()
    dictation_study = IntCol()
    dictation_finish = IntCol()
    date = DateCol(default=datetime.date.today(), unique = True)

class Iknow:
    def __init__(self,username):

        b = BeautifulSoup(urllib.urlopen("http://www.iknow.co.jp/user/"+username))

        iknow = b.find('div',id="study_badge_div").find('script').string
        self.iknow_study = int(re.search(r"int_left.*?(\d+)", iknow).group(1))
        self.iknow_finish = int(re.search(r"int_right.*?(\d+)", iknow).group(1))

        dictation = b.find('div',id="dictation_badge_div").find('script').string
        self.dictation_study = int(re.search(r"int_left.*?(\d+)", dictation).group(1))
        self.dictation_finish = int(re.search(r"int_right.*?(\d+)", dictation).group(1))

def create_graph():
    iknow_study = [i.iknow_study for i in RecKnow.select()]
    iknow_finish = [i.iknow_finish for i in RecKnow.select()]
    dictation_study = [i.dictation_study for i in RecKnow.select()]
    dictation_finish = [i.dictation_finish for i in RecKnow.select()]
    dates = [date2num(i.date) for i in RecKnow.select()]

    mondays   = WeekdayLocator(MONDAY)

    fig = figure(figsize=(9,5))
    ax = fig.add_subplot(111)
    ax.plot_date(dates, iknow_study,      'co-')
    ax.plot_date(dates, iknow_finish,     'mo-')
    ax.plot_date(dates, dictation_study,  'yo-')
    ax.plot_date(dates, dictation_finish, 'ko-')

    ax.xaxis.set_major_locator(mondays)
    ax.autoscale_view()
    ax.grid(True)
    fig.autofmt_xdate()

    title('iKnow Daily chart')
    xlabel('Date')
    ylabel('Score')

    legend(["iKnow study", "iKnow finished", "dict study", "dict finished"])

    fig.savefig(mygraph)

if __name__ == '__main__':
    if not os.path.isfile(mydb):
        RecKnow.createTable()

    iknow = Iknow(myname)
    RecKnow(iknow_study=iknow.iknow_study,iknow_finish=iknow.iknow_finish,
           dictation_study=iknow.dictation_study,dictation_finish=iknow.dictation_finish)
    create_graph()

みんなのPython Webアプリ編はみんなのPythonの続編

今朝Amazonから届いたので早速読んだ。

ProductName みんなのPython Webアプリ編 [みんなのシリーズ]
柴田 淳
ソフトバンククリエイティブ / ¥ 2,604 ()
在庫あり。

そして一通り流し読みした感想としては、Pythonがはじめての言語で、Webアプリまで作れるようになりたいと考えているヒトには最強な選択肢かもしれんなーと。

HTTPサーバー構築からはじまって、CGIで、ほらーHTMLとコードが混在して読みにくくなっちまうだろ、だからここでTemplateシステムが出てくんだよとか、Webのシステムはデータベースが必要でSQLとか使うとさくさく感の流れが途切れるし気持ち悪いじゃろ、そこでO/Rマッパーの出番なんだぜといった、MVCフレームワークに至るまでの過程がスマートに追っかけられる内容ですな。

もし、コードが書けない人員がアサインされたら、みんなのPythonとWebアプリ編をセットで渡して、これ読んどけって言う、間違いなく。

僕は、みんなのPython Webアプリ(上級)編みたいなものをイメージして予約してしまったのでちょっと予想と違ったかなと。Appendixにあるような内容を深く掘り下げてるのかなと思ったんだけど、さすがにみんなのPythonの続編でそれはないかと。

年末にでもちゃんと手を動かしながら、がつっと読みますヨ。