gae アプリ 開発メモ

Google App Engine アプリの開発メモ / 言語: python, javascript / ビギナー

blogの引越しを考え中

なんつーか、使いづらい。
Hatena blog。

だけで選んだんだけど、不満が募ってきた。

http://toc-gae-memo.blogspot.jp/ に引越しを画策中。
シンプルで自由度も高いのが決め手のポイントになってます。

ソースのカラー表示なんて機能、当たり前のようにない。
けど、css, javascript をワシャっと設定できるみたいなので、ソースのカラー表示も javascript でイケそうな予感がする。

もうひとつ。
ブログとは別にページを作成できる。

ブログの用途が
『自分の調べたことをまとめる』
なので、インデックスを作成できそうだ。

とはいえ、自由すぎる。
デザインや、ブログの投稿ルールをちょっと考えてみないとひどいことになりそうだ。

目下、一番の問題はこの Hatena blog にデータの Export 機能がないこと。
といっても、まだ件数も多くないから地道にやるべ。

絵文字ありのテキストファイルを処理する

ケータイメールのデータを処理するのに便利かな。

ポイントは codecs の encoding に 'shift_jis' ではなく 'mbcs' を指定する点。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import codecs

def main():
#    fin = codecs.open('sample.txt', 'r', 'shift_jis') # これでは encode 時にエラーが出る文字がある
    fin = codecs.open('sample.txt', 'r', 'mbcs') # こっちは正常に unicode 化される
    fout = codecs.open('out.txt', 'w', 'mbcs') # unicode から逆変換する

    for line in fin:
        print type(line) # 念のため line の型を調べる
        print >> fout, line,

if __name__ == '__main__':
	main()

print type(line) の結果は、ちゃんと

<type 'unicode'>

だった。

python 2.7の日本語ヘルプを構築する

ウチの環境(Windows 7 SP1 x64)では、Pythonドキュメント日本語翻訳プロジェクトで配布されている htmlhelp(.chm) はエラーが表示されて正常に動作しない。
なので、ドキュメントソースから構築してみた。
以下、手順。

準備

  1. sphinxが必要。
  2. Mercurialが必要。
  3. HTML Help Workshopが必要。

python-doc-ja からソースを取得する

コマンドプロンプトから

hg clone https://code.google.com/p/python-doc-ja/

でカレントディレクトリに python-doc-ja が作成され、ドキュメントソースがダウンロードされる。

ドキュメント作成に必要なユーティリティを取得する

cd python-doc-ja

python-doc-ja に入り、

make checkout

を実行すると必要なユーティリティが python-doc-ja\tools にダウンロードされる。

設定を変更する

ヘルプファイルの表示で出るエラーを回避する

既存のヘルプファイルは copybutton.js を実行しようとしてエラーが発生する。
ヘルプファイルではあまり意味がないので、copybutton.js を読み込まないように変更する。

python-doc-ja\tools\sphinxext\layout.html

の {% block extrahead %} ブロックを以下のように変更する。

{% block extrahead %}
    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
    {% if not embedded %}
    <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
    <script type="text/javascript" src="{{ pathto('_static/_jp.js', 1) }}"></script>
    {% endif %}
{{ super() }}
{% endblock %}

インデックスからの表示が失敗するエラーを回避する

インデックスからページを選択すると、ページがないという表示になる。
.hhk ファイル生成の問題を修正する。

python-doc-ja\tools\sphinx\sphinx\builders\htmlhelp.py

を変更する。

268~270 行目

                elif len(refs) == 1:
                    write_param('Local', refs[0])
                else:

                elif len(refs) == 1:
# modify begin
#                    write_param('Local', refs[0])
# modify change
                    ref = refs[0]
                    if isinstance(ref, tuple):
                        ref = ref[1]
                    write_param('Local', ref)
# modify end
                else:

271 ~ 274 行目

                    for i, ref in enumerate(refs):
                        # XXX: better title?
                        write_param('Name', '[%d] %s' % (i, ref))
                        write_param('Local', ref)

                    for i, ref in enumerate(refs):
                        # XXX: better title?
# add begin
                        if isinstance(ref, tuple):
                            ref = ref[1]
# add end
                        write_param('Name', '[%d] %s' % (i, ref))
                        write_param('Local', ref)

htmlhelp を作成する

コマンドプロンプトから

make htmlhelp

を実行する。

しばらくすると、

python-doc-ja\build\htmlhelp

に python27ja1.chm が作成される。

エラーなく完了すれば、これで作業はおしまい。

日本語はいろいろ大変そう

ウチの環境(windows 7 x64 SP1)では python 2.7 の htmlhelp はエラーが出て表示ができない。
エラーの原因は、ヘルプの html が jquery.js を使うように書かれているのに、jquery.js を読み込んでないため。
他の方はエラーが出てないんだろうか?
そもそも htmlhelp を利用してないんかな?

という訳で、エラーが出ない htmlhelp を構築しなおすことを試みてる。

手順は改めて書くとして、日本語を扱うにはいろいろ気を使いそうだ。

.css に日本語フォントを指定しただけでエラーが出てきた。

ダイアモンド継承とsuper()の続きの続き

ずっと、どこかで

super() は継承元への型変換みたいな仕組みを提供してる

と思い込んでた。
これが大きな間違いのはじまり。

道理で、super()の文章を何度読んでも釈然としないわけだ。

動的な実行環境下での複数の継承の共同をサポートすることです。
この用途は Python 特有で、静的にコンパイルされる言語や、単一の継承しかサポートしない言語では見られないものです。
これは複数の基底クラスが同じメソッドを実装する “diamond diagram” を実装できるようにします。
良い設計のために、このメソッドがすべての場合に同じ形式で呼び出せるべきです。
(呼び出しの順序が実行時に決定されることや、順序がクラスの階層の変更に対応することや、その順序には実行時まで未知の兄弟クラスが含まれえることが理由です)

この文章の意味は、

super()は「適切」かつ「まんべんなく」上位クラスのメソッドを呼ぶための仕組みを一定の記述で提供する。
つまり、継承元の仕事をキッチリこなす。

ってことだ。

次の例のコードの動作でようやくわかった。

class A(object):
    def talk(self):
        print 'This is A.'

class B(A):
    def talk(self):
        print 'This is B.'
        super(B, self).talk()

class C(A):
    def talk(self):
        print 'This is C.'
        super(C, self).talk()

class D(B, C):
    def talk(self):
        super(D, self).talk()

def main():
    d = D()
    d.talk()

if __name__ == '__main__':
    main()

このとき、D.talk()では

super(D, self).talk()

だけを呼んでる。

その結果、

This is B.
This is C.
This is A.

となる。
ちゃんと継承元の talk() をまんべんなく呼び出してる。
呼び出しの重複もない。

道理で super() を説明するために、みんな __init__() で説明するわけだ。
__init__() とかは、こう動いて欲しいもん。

Python's Super is nifty, but you can't use itで説明されてる大事な話。

親クラスに super() を記述してないクラスがあると、そこでメソッドチェーンは途切れてしまう

という点は要注意。


最後に。
『特定のクラスの仕事だけしてくれ』ってときは、迷わず

C.talk(self)

でいいんだ。

ダイアモンド継承とsuper()の続き

ダイアモンド継承とsuper()の続き

super()の理解がまだ足りない

先程、【super()で C.talk() が呼び出されるように指定してみる】で

class D(B, C):
    def talk(self):
        super(C, self).talk() # C を明示する

def main():
    d = D()
    d.talk()

の結果は

This is A.

となったが、これは C.talk() を探したわけではないみたい。

super オブジェクトの意味は、

指定クラスの親クラスを指す

らしく、

super(C, self).talk() は (C の親 = A).talk() を呼び出す。

と動いた。

というのも、

class C(A):
    def talk(self):
        print 'This is C.'

としたとき、

This is A.

を返してきたから。

ダイヤモンド継承をしたときの super() の使い方がようわからん。
という訳で、フリダシに戻る。

class D(B, C):
    def talk(self):
        C.talk(self)

とすればいいのは、分かってんだけどね。