メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2008年2月2日土曜日

[Apache][CodeReading] Apache2.2.8解読開始

pukiwiki入れて早速Apache2.2.8の解読を開始。

ステップ数を見てみたらtest入れないでざっと296119行。
総ファイル数はtest入れないで678ファイル。

標準で添付されているモジュールは全て含む。

結構な量である。読み終わるころにはApache3とかApache4とか出ているかもしれないね。
いや、楽しみだ。

目標というかルールは・・・
毎日読む。ちょっとづつ。3日坊主OK。

な感じ。



.

[mod_chxj][携帯] DoCoMo→DoCoMo変換ルーチン追加

POSTデータのDoCoMo→DoCoMo変換ルーチン追加完了。

次はGETデータの変換。

[Python][お勉強] Python入門(16) - printステートメント

printステートメントについて見ていく。


printステートメントとは

オブジェクトをテキストに変換して標準出力ストリームに書き込む文のこと。


printステートメントの書き方

ステートメント説明
print spam, hamsys.stdoutにオブジェクトを出力する。項目と項目の間(カンマの位置)に自動的にスペースが入る。
print spam, ham,sys.stdoutにオブジェクトを出力する。項目と項目の間にスペースが入る。末尾のカンマは「改行文字が入らない」の意。
print >> myfile, spam, hamオブジェクト(テキスト)をsys.stdout.writeではなくmyfile.writeに送る


printステートメントのデフォルトの出力先はsys.stdoutである。sys.stdoutは標準出力を表す。
改行を入れたくない場合はステートメントの最後にカンマを入れる。

で、やってみっぺ。

>>> print "a","b",
a b
>>> print "a","b"
a b


トップレベルからでは改行されているのかされていないのかわからない・・・。

文字列フォーマットとprintステートメントのあわせ技

>>> print "Hello, %s" % "abc"
Hello, abc
>>>


ふーん。
同じことをsys.stdoutを使ってやってみる。
同じことをするにはsysモジュールをimportする。

>>> import sys
>>> sys.stdout.write('Hello, abc\n')
Hello, abc


うむ。できた。


出力先を変更する例
printステートメントの出力先をたとえばファイルにする場合。

>>> import sys
>>> sys.stdout = open('log.txt', 'a')
>>> print "aaa bbbb ccccc"
>>> sys.stdout = sys.__stdout__
>>>  # ここでCTRL+D
$ cat log.txt
aaa bbbb ccccc



標準出力からlog.txtへ変更した。log.txtにはprintした値が書かれている。
最後のsys.stdout = sys.__stdout__は、sys.stdoutの値を変更したので、元に戻している。
まったく同じことを「>>」を使用して行うことができる。


>>> log = open('log.txt','a')
>>> print >> log, "a", "b", "c"
>>> print "a", "b", "c"
a b c
>>> log.close()
>>>


>>を使用すると標準出力も機能したままとなるので便利。




おしまい。

[Python][お勉強] Python入門(15) - 拡張代入ステートメント

いわゆる代入演算子。

それだけ。


代入ステートメントの例。

x += yx &= yx -= yx |= y
x *= yx ^= yx /= yx >>= y
x %= yx <<= y x **= y x //= y

評価回数1回ですむ。

以上。

[Python][お勉強] Python入門(14) - 変数名命名ルールと慣例

変数名のつけ方にPython流の慣例があるようだ。また、Python内部で使用されている特別な変数に使用されている名前とかぶらないためにも従っておいた方が無難。

まずルールから。


ルール

  • 先頭は英文字か下線。2文字目以降は英字数字下線のいずれか。
  • 大文字・小文字は区別される。
  • 予約語は変数として使用できない。
予約語一覧
anddelforisraise
asserteliffromlambdareturn
breakelseglobalnottry
classexceptiforwhile
continueexecimportpassyield
deffinallyinprint



慣例
  • __name__などのように先頭と末尾に2つ重ねたアンダースコアをつける名前は付けない。
  • _xなど先頭にアンダースコアを1つつけた名前は付けない。
  • __xなど先頭だけにアンダースコアを2つつけた名前は付けない。(マングリング対象になる)
  • _などアンダースコア1つだけで構成される変数名は付けない。この名前は対話型コマンドラインでは直前に実行された式の演算結果を保持するのに使用されている。$_に似た感じか。


終わり。




.

[Apache][CodeReading] Apache2.2.8のソースを読もうかと。

ひらメソッドなるものを使用してApache2.2.8のソースを読んでみようと
心に誓った。毎日ちょっとづつ。
今まではそういったリーディングメソッドは一切使用しなかったので相当気合いれないと読めなかったんだけど、ひらメソッドはどうだろうか。機械的に読めそうな感じなのでとっても期待している。
Wikiを使用するんだけど、そこそこ情報がたまったら公開してみようかと思うのであった。


ちなみに今までノーメソッドで読破したソースは

  • 1990年代のgcc(さっぱりわからなかったが、とにかく読んだ・・・) ==>成果物なし
  • Linuxカーネル0.1(リーナスさんオンリーのソース)
  • Linuxカーネル2.2系のどれか忘れた(バニラ。ドライバ以外。ファイルシステムはExt2のみ)
  • Linuxカーネル2.4系のどれか忘れた(バニラ。ドライバ以外。ファイルシステムは含まず)==>成果物:lsしまくると固まるOS完成。ファイルシステムはスクラッチで書いたExt2。
  • djbdns-1.05(非常におもしろかった。)==>成果物:ひたすらパラメータでレコードを指定するしょぼいDNS完成。
その他いろいろかいつまんでよんだけど何読んだか忘れた。
Linuxカーネル2.2とLinuxカーネル2.4を読むのに大体5年くらいかかった気がする。。。



.

[Python][お勉強] Python入門(13) - 代入ステートメント

これまではプリミティブなオブジェクトについて見てきたが、いよいよプログラミングっぽいところに入る。
最初は代入ステートメントらしい。

代入ステートメント
=という記号を使用して右辺のオブジェクトリファレンスを左辺の変数に代入する。
代入ステートメントを使用するにあたっての注意点は以下のとおり。

  • 代入するとオブジェクトのリファレンスが作成される。
  • 変数はオブジェクトを代入すると作成できる。
  • よって値の代入されていない変数は使用できない。
  • =記号なしで代入が行われるパターンがある。

代入ステートメントの基本的な形

代入ステートメントの基本的な形は以下のとおり。
ステートメント説明
spam = 'Spam'基本的な代入
spam, ham = 'spam', 'ham'タプル代入
[spam,ham] = ['spam','ham']リスト代入
spam = ham = 'lunch'マルチターゲット

1行目の例はよしとして、2行目は文字列'spam'のリファレンスが変数spamに代入され、文字列'ham'のリファレンスが変数hamに代入される。3行目も右辺の文字列'spam'のリファレンスが左辺の変数spamに代入され右辺の文字列'ham'のリファレンスが左辺の変数hamに代入される。
2行目、3行目の代入のことを「アンパック代入」という。
4行目は文字列'lunch'のリファレンスが変数hamと変数spamに代入される。このような代入のことを「マルチターゲット代入」という。


さっそく実際にやってみる。
タプル代入。

>>> a , b = 10, '20'
>>> a
10
>>> b
'20'
>>> a, b = (20, '30')
>>> a
20
>>> b
'30'


リスト代入。

>>> [a,b]=[1,2]
>>> a
1
>>> b
2
>>> [a,b]=[b,a]
>>> a
2
>>> b
1


ほっほう。

マルチターゲットはいいや。

タプル代入とリスト代入は、左辺の要素数と同数の要素さえ持っていれば別の型のシーケンスを指定することもできる。

>>> a,b,c,d,e,f,g="abcdefg"
>>> a,b,c,d,e,f,g
('a', 'b', 'c', 'd', 'e', 'f', 'g')
>>> a,b,c,d,e,f,g="abcdefg"
>>> a,b,c,d,e,f,g
('a', 'b', 'c', 'd', 'e', 'f', 'g')
>>> [a,b,c,d,e,f,g]='gfedcba'
>>> [a,b,c,d,e,f,g]
['g', 'f', 'e', 'd', 'c', 'b', 'a']
>>> [a,b,c,d,e,f,g] = (g,f,e,d,c,b,a)
>>> [a,b,c,d,e,f,g]
['a', 'b', 'c', 'd', 'e', 'f', 'g']

こりゃらくだ。


数値を生成してくれる便利関数もある。

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5)
[0, 1, 2, 3, 4]



なるほど。ここまではOK。




.

2008年2月1日金曜日

[mod_chxj][携帯] 次はDoCoMo→DoCoMo変換をやる

とりあえず、

  • SoftBank→iMode
  • EzWeb→iMode
のPOSTデータ絵文字変換は完了。

次は
  • DoCoMo→DoCoMo
のPOSTデータ絵文字変換をする。
仕組み上、DoCoMoでも変換が必要。
変換順は以下のとおり。
  1. DoCoMo絵文字(SJIS/UTF-8)をメタ絵文字に変換
  2. メタ絵文字をDoCoMo絵文字(SJIS/UTF-8/EUCJP-WIN)に変換



.

[mod_chxj] 思いつきメモ

持たせたいモードは2つ。

  • 現状作っているDoCoMoの絵文字マップにあわせてサーバサイドアプリに渡すモード。
  • なんの加工もしないでサーバサイドアプリに渡すモード。
DoCoMoの絵文字マップにあわせるパターンの場合、DoCoMo絵文字マップに無い絵文字はただの文字列になる。
何の加工もせずにサーバサイドアプリに渡すモードの場合は、クライアント端末に返すタイミングでのみそれぞれの端末にあった絵文字に変換する。つまりauで表示できるものについては必ずauで表示でき、DoCoMoで表示できるものについては必ずDoCoMoで表示でき、SoftBankで表示できるものについては必ずSoftBankで表示できるようにする。


懸念点は、UNICODEが重なっている問題か。


ちなみに、ただの思いつきメモ。実装するかどうかは別問題。





.

[mod_chxj][携帯] EUCテストサイトサンプル

絵文字のテスト用のEUC-JPで書かれたテストサイトを追加した。


SoftBankとauで閲覧、POSTともにOK。



.

[vim] 開いているファイル全てをいっきに置換するには

vimちっぷす。


$ vim *.txt

って開いたファイルの中に含まれている"SJIS"という文字列を全て"EUCJP"に一気に置換するには、


コマンドモードから以下を入力。

:bufdo %s/SJIS/EUCJP/g |update


ちなみに最後の

|update

は「更新したら保存する」という意味らしい。



.

[mod_chxj][携帯] とりあえずcvsにあげておく

cvsにコミットしといた。

でも、動作しない版。

なぜならばDoCoMoの場合、ダミールーチンが起動するようになってるから。



.

[mod_chxj][携帯] SoftBank→imode絵文字 ウェブコード変換対応完了

端末がSJISの場合で且つウェブコード(GL領域を使うコード)の場合がPOSTされてきてもOKになった。
連続した絵文字もOK。

全絵文字でチェックしたんでOK。



ところで、SJISのウェブコードでないバイナリコードの仕様はどこにあるんだろう・・。





.

[vim] 置換

どうでもいいこと。


1b24515e0f
1b24515d0f
1b24515c0f


という文字列から頭の1b24と最後の0fをとり省きたいとする。



:%s/1b24\(....\)0f/\=printf("%s", submatch(1))/g



どうでもいいことでしたー。

ちないみにvim7ね。



.

[Python][お勉強] Python入門(12) - 比較

比較をやる。


Pythonでは全てのオブジェクトは比較できる。どちらが「大きいか」「同等か」を判定できる。

==演算子
オブジェクトが同等のものであるかどうかを比較する。
まったく同じメモリ領域にあるかどうかではなく、オブジェクトの保持する値が等しいかどうかを比較する。

is演算子
オブジェクトが同一かどうかを比較する。
まったく同じメモリ領域にあるかどうかを比較する。

さっそく上記2つの演算子をやってみる。


>>> L1 = [1, ('1', 3)]
>>> L2 = [1, ('1', 3)]
>>> L1 == L2
True
>>> L1 is L2
False
>>>

L1とL2の値は「同等」だが別メモリ領域に確保されているので「同一」ではない。
==演算子での場合は「同等」かどうかを比較する。比較結果はTrue。
is演算子での場合は「同一」かどうかを比較する。比較結果はFalse。


>>> L1 = [1, ('1', 3)]
>>> L2 = L1
>>> L1 == L2
True
>>> L1 is L2
True
>>>

今度はL1を生成後リファレンスをL2に代入した。
この場合L1とL2は「同一」となる。よって、L1 == L2はTrueを返しL1 is L2もTrueを返す。



>>> S1 = 'spam'
>>> S2 = 'spam'
>>> S1 == S2
True
>>> S1 is S2
True
>>>

文字列の場合は少々状況が違う。短い文字列の場合Pythonにキャッシュされて、そのキャッシュされた内容が再利用される。そのため上記は「同一」と判定される。文字列はimmutableであるから特に問題はないがキャッシュさせたくない場合は長い文字列を生成してやればよい。

>>> S1 = 'a longer string'
>>> S2 = 'a longer string'
>>> S1 == S2
True
>>> S1 is S2
False
>>>



<演算子
左辺が右辺よりも小さいかどうかを判定する。小さい場合にはTrueを返す。両辺にリスト、ディクショナリを指定した場合はそのオブジェクトの全要素が走査、比較される。

>>> 1 <>>> 2 <>>> L1 = [1, (2, 3)]
>>> L2 = [1, (2, 1)]
>>> L1 == L2
False
>>> L1 <>>> L2 <>>>




>演算子
左辺が右辺よりも大きいかどうかを判定する。大きい場合にはTrueを返す。リスト、ディクショナリを辺に指定した場合には全要素が走査対象となる。

>>> 1 > 2
False
>>> 2 > 1
True
>>> L1 = [1, (2, 3)]
>>> L2 = [1, (2, 1)]
>>> L1 > L2
True
>>> L2 > L1
False
>>>




True/False
PythonにはTrueとFalseというブール型オブジェクトがある。
何かが真のときはTrueで偽のときはFalse。また、プログラム中ではTrueは1、Falseは0に評価される。

>>> 1 + True
2
>>> 3 + True
4
>>> 3 + False
3
>>>





どのような場合にTrueか。どのような場合にFalseか。
どのような場合にTrueと評価され、どのような場合にFalseと評価されるかをみていく。
基本的には以下のとおり。
  • 数値の場合0で無ければTrue
  • その他のオブジェクトは空でなければTrue
  • NoneオブジェクトはFalse
NoneオブジェクトはCで言うところのNULLにあたるもの。

例を表に記す。


オブジェクトtrueかfalseか
"spam"True
""False
[]False
{}False
1True
0.0False
NoneFalse



型ごとの比較ルール
  • 数値の場合は大きさが単純に比較される
  • 文字列の場合は文字1つ1つについて比較され、アルファベット順で後のものほど「大きい」と判定される。
  • リスト、タプルの場合、左から順に1つ1つ比較される。
  • ディクショナリの場合はキーと値のリストとしてソートされ、1要素づつ比較される。

おしまい。




.

[Python][お勉強] Python入門(11) - ビルトイン型の分類

今日もPythonをやりまうす。
ビルトインオブジェクトの型の分類のまとめ

オブジェクトの型カテゴリ上書きの可否
数値数値不可
文字列シーケンス不可
リストシーケンス
ディクショナリ写像
タプルシーケンス不可
ファイルエクステンション該当無し



だそうです。「上書きの可否」項目が不可となっているものがimmutableなオブジェクト。
要注意。



おわり。
.

[mod_chxj][携帯] softbank→imode変換 ウェブコード全滅

SoftBankの絵文字をSJISでPOSTしてみると、

当初ウェブコードで一文字づつ


0x1b 0x24 [?] [?] 0x0f

という感じのコードが飛んでくるかと思っていた。

1文字だけの場合は問題ないのだが、複数文字連続で絵文字を送信してみると

0x1b 0x24 [最初の絵文字のコード1][最初の絵文字のコード2]
[2番目の絵文字のコード]・・・・・0x0f


のようにまとめられて飛んでくる。。

知らなかった。

0x1b24がシフトイン、0x0fがシフトアウトな感じなのかしら。。

ウェブコンテンツ開発ガイドを見ると・・・33pぐらいに書いあるね・・・・。


.

2008年1月31日木曜日

[mod_chxj][携帯] SoftBank 3G携帯でウェブコードでないSJISコードをPOSTしてくる

そもそもそういうものなのか?

一応全コード洗い出して、SoftBankで入力できる絵文字は入力してみた。
全てOK。

一文字づつ実際に入力してPOSTしてみたので、結構疲れた。

やはり携帯系は実機いじるのがいちばん面倒。。


これからもう一度端末側コードをUTF-8に設定して全絵文字POSTテストをする予定。
SoftBank3G携帯の場合はデフォルトでUTF-8にしておくのであまり意味がないかもしれないけど、
あとSJIS時にウェブコードを送ってくる端末でもテスト予定。



.

[Python][お勉強] Python入門(10) - ファイル

ファイルオブジェクトについて見ていく。

目標

  • ファイルオブジェクトについて理解する。
  • ファイルの基本的な操作を覚える。

ファイルオブジェクトとは
マシン上に存在するファイルへのリンクオブジェクトで、ファイルを操作する場合に使用する。
疑問:ファイルであれば操作できるのか?たとえばデバイス等。多分できるんだろうね。


ファイルオブジェクトのカテゴリ
ファイルオブジェクトは「シーケンス」でも「写像」でも「数値」でもない。
じゃあ、なんだ?次のセクションを見るとどうも「エクステンション」カテゴリーらしい。。


ファイルの基本的な操作
操作説明
fp = open('/tmp/spam', 'w')出力ファイルのオープン
fp = open('data', 'r')入力ファイルのオープン
s = fp.read()ファイル全体読み込み。内容を1つの文字列にする
s = fp.read(N)Nバイト読み込み(Nは1バイト以上)
s = fp.readline()行の読み込み(行末記号含む)
L = fp.readlines()ファイル全体読込。内容を文字列のリストとして返す
fp.write(S)文字列Sをファイルに出力
fp.writelines(L)文字列のリストLを全てファイルに出力
fp.close()ファイルのクローズ。ガーベージコレクションの対象になれば自動でクローズされる。




上記を使ってみる。

$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> fp = open('aaa','w')
>>> fp.write('hello world\n')
>>> fp.close()
>>>
$ cat aaa
hello world
$

オープン、クローズ、書き込みをしてみた。
次は読み込んでみる。

$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> fp = open('aaa','r')
>>> S = fp.read()
>>> fp.close()
>>> S
'hello world\n'
>>>


読めました。
次、複数行パターン。


$ cat aaa
hello world1
hello world2
hello world3
hello world4
$ python
Python 2.4.4 (#2, Apr 5 2007, 20:11:18)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> fp = open('aaa','r')
>>> L = fp.readlines()
>>> fp.close()
>>> L
['hello world1\n', 'hello world2\n', 'hello world3\n', 'hello world4\n']
>>>



複数行の出力も。

>>> fp = open('aaa', 'w')
>>> fp.writelines(['a\n','b\n','c\n'])
>>> fp.close()
>>>
$ cat aaa
a
b
c
$




まとめ
  • ファイルオブジェクトは「数値」でも「シーケンス」でも写像でもない。
  • ファイルの基本的操作open、close、read、write、readline、writeline、readlines、writelines。
  • ファイルオブジェクトが破棄されると自動でクローズされる。
  • とりたてて注目すべきところは無い気がする。


.

2008年1月30日水曜日

[mod_chxj][携帯] softbank→imode絵文字変換ルーチン完成

softbank→imode絵文字変換ルーチン完成。

UTF8→EUCJP/SJIS/UTF-8へポストデータを変換します。

で、SoftBank 3G携帯(822SH)をSJISでPOSTされてくるようにしてやってみると・・・、
ウェブコードが送られてくるはずがよくわからないコードが送られてくる。。

なんじゃこりゃ。

要調査。

で、とりあえず入力できる絵文字を全てPOSTしてみた。
その結果→http://spreadsheets.google.com/pub?key=p5XOtho4dsT_MeiB1iEJUbQ




.

[Python][お勉強] Python入門(9) - タプル

タプルをやる。

最終目標

  • タプルを理解する。
  • タプルの基本的操作を覚える。
といった感じ。

タプルとは
複数のオブジェクトを保持することができるリストやディクショナリに似たオブジェクト(コレクション)。
リストやディクショナリに似ているが、immutable。またリストやディクショナリと違ってメソッドを保持しない。カテゴリは「シーケンス」。

つまり、柔軟性のないリスト。



タプルの基本的操作


タプルの基本的操作を以下に列挙する。
操作説明
()空タプルの生成
t1 = (0,)要素を1つだけ含むタプルの生成(カンマに注意)
t2 = (0,1,2,3)4つの要素を含むタプルの生成
t2 = 0, 1, 2, 34つの要素を含むタプルの生成
t3 = ('a', ('b', 'c'))ネスト
t1[0]インデクシング
t3[1][2]インデクシングのインデクシング
len(t1)長さ
t1 + t2連結
t1 * 100繰り返し
for x in t2ループ
x in t2特定の要素が含まれているかの確認


ひとつの要素を生成する場合には、「(0,)」と要素の後ろにカンマを入れなければいけないらしい。
実際にやってみる。

>>> t1 = (0)
>>> t1
0
>>> t1[0]
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unsubscriptable object

カンマを入れないとt1[0]で参照できない。カンマを入れない場合は上記の場合整数として扱われる。


>>> t1 = (0,)
>>> t1[0]
0
>>> t1
(0,)


カンマを入れるとタプルとして生成され、t1[0]でも参照できる。

だれが見てもタプルであるとわかれば、()は必ずしも書かなくてよい。

>>> t1 = (1,2,3)
>>> t1
(1, 2, 3)
>>> t1 = 1,2,3
>>> t1
(1, 2, 3)



連結や繰り返し、インデクシングやスライシングなんかもリストと同じように行える。

>>> t1 = (1,2,3)
>>> t2 = (4,5,6)
>>> t1 + t2
(1, 2, 3, 4, 5, 6)
>>> t1 *4
(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)
>>> t1[2]
3
>>> t3 = t1 + t2
>>> t3
(1, 2, 3, 4, 5, 6)
>>> t3[2:4]
(3, 4)



タプルはimmutableなので変更できない。ソートなどをしたい場合はいったんリストに変換する。

>>> t3 = (6,5,5,3,6)
>>> t3
(6, 5, 5, 3, 6)
>>> L1 = list(t3)
>>> L1
[6, 5, 5, 3, 6]
>>> L1.sort()
>>> L1
[3, 5, 5, 6, 6]
>>> T = tuple(L1)
>>> T
(3, 5, 5, 6, 6)


タプルからリストに変換するにはlist()関数を使用し、リストからタプルに変換するにはtuple関数を使用する。


まとめ
  • タプルはリストやディクショナリに似たオブジェクト。
  • タプルはimmutableで変更できない。
  • リストに似た操作を行える。
へぇ。



.

[mod_chxj][携帯] ezweb->imode絵文字変換ルーチン完成

auだけだけど、ezweb→imode絵文字変換ルーチンが完成した。

ezweb(UTF-8/SJIS)→imode(UTF-8/SJIS/EUC-JP)がOK。

サーバのアプリからはあたかもimodeがアクセスしている感じになる。(絵文字だけ)


だけど、動的QRコードがおかしい。。。


==>間違って画像の場合も絵文字変換かけてしまっていたので修正。
.

2008年1月29日火曜日

[Python][お勉強] Python入門(8) - ディクショナリ

さて、次はディクショナリなるものを学ぼうと思う。

最終目標

  • ディクショナリとはなんぞや
  • ディクショナリに対する基本的操作を覚える
ことを目標にする。



ディクショナリとは

簡単に言えば、「連想配列」とか「ハッシュ」といわれているもの。
Pythonのビルトインオブジェクトの中で最も柔軟性に富んだもので、リストとは違って要素を順不同で保持している。また、リフトでは添え字によってアクセスしていたが、ディクショナリでは「キー」によってアクセスする。




基本的操作

ディクショナリに対する基本的操作を以下に記す。
操作・演算説明
D1 = {}空のディクショナリを生成
D2 = {'spam' : 2, 'eggs' : 3}要素二つのディクショナリの生成
D3 = {'food' : {'ham' : 1, 'eggs' : 2}}ネスト
D2['eggs']キーによるインデクシング
D2.has_key('eggs')
'eggs' in D2
D2.keys()
D2.values()
D2.copy()
ディクショナリのメソッド
len(D1)長さ(要素数)取得
D2[key] = 42
del D2[key]
要素の追加・変更・削除
D4 = dict(zip(keyslist, valslist))ディクショナリの作成


とりあえずやってみる。

ディクショナリ生成から。

>>> d2 = {'spam' : 2, 'ham' : 1, 'eggs' : 3}
>>> d2['spam']
2



ふむ。注意点としては、読み出すときには"{}"じゃなくて"[]"を使用するということ。

そして、

>>> d2
{'eggs': 3, 'ham': 1, 'spam': 2}



生成したときと違う順番で表示された。つまりこれが順不同?順番は不定。

で、長さを取得してみる。

>>> len(d2)
3


リストと同じ操作で取得できる。覚えるのが楽。

次は検索をやってみる。

>>> d2.has_key('ham')
True
>>> d2.has_key('aaa')
False
>>> 'spam' in d2
True
>>> 'aaa' in d2
False


これも楽勝。

キー一覧を取得。

>>> d2.keys()
['eggs', 'ham', 'spam']

どっかによくあるkeysメソッド。

値一覧取得。

>>> d2.values()
[3, 1, 2]

これもどっかによくあるvaluesメソッド。

多分、keysで取得したデータの順番はvaluesで取得したデータの順番と
同じではない、と思っていた方が後々はまらずに済みそうだ。


次は追加と削除。

>>> del d2['spam']
>>> d2
{'eggs': 3, 'ham': 1}
>>> d2['brunch'] = 'Bacon'
>>> d2
{'eggs': 3, 'brunch': 'Bacon', 'ham': 1}


問題なし。


getメソッドを使用すれば値が存在しない要素にアクセスした場合にデフォルト値を返すようにすることができる。

>>> d2.get('spam',10)
10
>>> d2.get('ham',20)
1


d2.get('spam',10)では先ほど削除した要素なので、デフォルト値10が返されている。


updateメソッドを使用すれば2つのディクショナリをマージすることができる。
重複したキーがある場合、updateメソッドのパラメータで渡されたディクショナリの方の値に上書きされる。

>>> d2
{'eggs': 3, 'brunch': 'Bacon', 'ham': 1}
>>> d3 = {'toast':4, 'muffin':5,'brunch': 6}
>>> d2.update(d3)
>>> d2
{'toast': 4, 'ham': 1, 'muffin': 5, 'eggs': 3, 'brunch': 6}
>>>




まとめ

特徴は以下のとおり。
  • キーによって要素にアクセスする。
  • 要素は順不同で保持。
  • 長さ変更自由
  • ネスト可(リストもそうだった。。)
  • 「写像」というカテゴリに属している
  • 存在しない要素に代入すると新たに要素が作成される
  • キーは文字列じゃなくてもよい

注意点としては、リストと混同しないようにすることと代入すると新しい要素が作られる
ということと順不同ということか。



.

[その他] ラベルをタイトルにつけてみた

アーカイブに出てくるタイトルは何がなんだかわからないので、
[ラベル]な感じでラベル名を書くようにした。。

自動でできないのかなぁ。。


..

[mod_chxj][携帯] CDATAセクション

CDATAセクションも理解できるようにパーサを変更。

これでemoji.xmlに


<no><![CDATA[(<人>)]]></no>


なんてのがかけるようになった。




.

[C言語][mod_chxj] 可変長マクロ

どうでもよいが、gccの可変長マクロ。


#define DBG(rec,format, args...) \
ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0,(request_rec*)(rec),(format), ##args)



な感じ。

[mod_chxj][携帯] ezweb→imodeの定義ファイル読込ルーチン完了

ezweb→imode定義ファイルの読み込みまで完了。

次は、ezweb→imodeの定義を使用してPOSTデータを改変してみる。

その前に、定義ファイル中に<とか>とかあるんで、XMLパーサに<![CDATA[]]>セクションを
つけなきゃ・・・。

うーむん。expat使えばよかったかも。
でも楽しいからいいや。



.

[mod_chxj][携帯] SoftBank→imode絵文字変換

これもezweb→imode絵文字変換と同様。

xmlは、


<softbank2imode>
<set>
<no>1</no>
<softbank>
<sjis-hex>1b2447210f</sjis-hex>
<utf8-hex>ee8081</utf-hex>
</softbank>
<imode>
<no>140</no>
</imode>
</set>
</softbank2imode>


となっているんで、

typedef struct softbank2imode_t {
struct softbank2imode_t *next;
int no;
emoji_data_t softbank_sjis;
emoji_data_t softbank_utf8;
int imode_no;
} softbank2imode_t;

な感じ。

検索用インデックスをmod_chxj_configに追加して・・・

softbank2imode_t *emoji_softbank2imode[EMOJI_SOFTBANK2IMODE_COUNT];


で終了。

次は絵文字データロード部分を修正す。




.

2008年1月28日月曜日

[mod_chxj][携帯] ezweb→imode絵文字変換

ezweb→imodeの絵文字変換用データ構造は結局以下のXmlを保存できればよい。


<ezweb2imode>
<set>
<no>1</no>
<ezweb>
<sjis-hex>F659</sjis-hex>
<utf8-hex>eebd99</utf-hex>
</ezweb>
<imode>
<no>220</no>
</imode>
</set>
</ezweb2imode>


だもんで、


typedef struct ezweb2imode_t {
struct ezweb2imode_t *next;
int no;
emoji_data_t ezweb_sjis;
emoji_data_t ezweb_utf8;
int imode_no;
} ezweb2imode_t;


な感じで良いのでは。
あと、必要そうなのは、sjisコードで検索するためのインデックス配列と
utf8コードで検索するためのインデックス配列。

これはmod_chxj_configの中に持たせれば良いか。

ezweb2imode_t *emoji_ezweb2imode[EMOJI_EZWEB2IMODE_COUNT];

な感じか。

はい、終了。

[mod_chxj][携帯] 絵文字関連のデータ構造

なんでemoji構造体がmod_chxj.h内にあるんだっけ。
ということでとりあえずemoji関連はchxj_emoji.hに移動。



[Python][その他] Pythonってはやっているの??

今日久々に本屋にいってみた。特に何を買うわけでもなく。
で決まってコンピュータ書籍コーナへ。

以前はPythonといったら「初めてのPython」と「プログラミングPython」ぐらいだったと思う。
今は数冊、いろいろなのが出ているようだ。。

うーむ。興味深い。

そのほか、ErlangとかLuaの本もあった。今度読んでみようと心に誓ってみた。

[mod_chxj][携帯] POSTされてきたデータのコード変換 - マッチングテーブル定義作成(xml) DoCoMo編

DoCoMoは基本的に何もしないで良いと思っていたが、サーバサイドの文字コードが任意に指定できるため、やはり変換かけないとダメ。

定義ファイルを作ってみて全体設計の変更が必要になったので以下に書いておく。

  1. クライアントの文字コードを特定する
  2. クライアントの機種を特定する
  3. 絵文字をメタ絵文字に変換する。
  4. 文字コードを変換する。
  5. メタ絵文字を絵文字に変換する。
  6. サーバサイドに渡す
といった感じになるかと思う。
ここでも内部的にはメタ絵文字を使用して変換かけないとダメと気づいた。

それでは、DoCoMoの定義ファイルを作ってみる。

・・・と思ったけど、DoCoMoの定義は既にある定義でまかなえるのでやらなくて良いことが判明。。
ということで次はSoftBankの定義をする。

SoftBank → imodeの変換をするための定義考える。

必要なのは、SoftBank機から送られてくる文字コードUTF-8の場合とSJISの場合、
そして送られてきた文字コードにひもづくDoCoMoの絵文字番号。

ということでできたxmlを以下に記す。

<softbank2imode>
<set>
<no>1</no>
<softbank>
<sjis-hex>1b2447210f</sjis-hex>
<utf8-hex>ee8081</utf-hex>
</softbank>
<imode>
<no>140</no>
</imode>
</set>
<set>
<no>2</no>
<softbank>
<sjis-hex>1b2447220f</sjis-hex>
<utf8-hex>ee8082</utf-hex>
</softbank>
<imode>
<no>140</no>
</imode>
</set>
・・・略・・・
<set>
<no>3</no>
<softbank>
<sjis-hex>1b2447230f</sjis-hex>
<utf8-hex>ee8083</utf-hex>
</softbank>
<imode>
<no>149</no>
</imode>
</set>
</softbank2imode>


これをetc/emoji.xmlの中に追記し、
読み込みロジックの追加とデータ構造追加し、
変換ルーチンを追加すればOKのはず。

[Python][お勉強] Python入門(7) - リスト

今回はPythonにおけるリストを学ぶ。

最終目標

  • リストを理解する。
  • リストの基本的操作を覚える。

リストとは

「一定の順序でならんだオブジェクトの集合」とのこと。
ま、いわゆるリスト。ここはOK。

さらにPythonでは、

  • 要素の型を問わない。
  • インデックスによって要素にアクセスできる
といった特徴がある。
・・・別にPythonに限ったことではない。。

  • 「シーケンス」カテゴリ
  • オブジェクトリファレンスの配列
らしい。
ここであたらしくカテゴリという言葉が出てきた。これは、Pythonではビルトインオブジェクトは大きくいくつかのカテゴリに分けることができる。同じカテゴリであればほぼ同じ操作を行える。カテゴリには以下の3つがあるらしい。
  • 数値
  • シーケンス
  • 写像

で、文字列もリストも「シーケンス」に分類される。だから文字列に対する操作とリストに対する操作が似た感じになる。

次の項目にオブジェクトリファレンスとあるが、リストは正確にはオブジェクトへのリファレンスの配列なのだそうだ。簡単に言えばポインタの配列。ただし可変長。



リストの基本的な操作

リストの基本的な操作を以下に列挙する。

操作説明
L1 = []空リストの作成
L2 = [0, 1, 2, 3]4つの要素を含むリストの作成
L3 = ['abc',['def','ghi']]リストのネスト
L2[i]インデクシング
L3[i][j]インデクシングのインデクシング
L2[i:j]スライシング
len(L2)長さの確認
L1 + L2連結
L2 * 3繰り返し
for x in L2
3 in L2
ループ、特定の要素が含まれているかの確認
L2.append(4)
L2.extend([5,6,7])等
メソッド
del L2[k]
del L2[i:j]
L2.pop()
L2[i:j] = []
リストの縮小
L2[i] = 1
L2[i:j] = [4,5,6]
インデックスを指定しての値変更
range(4)整数のリスト
xrange(0, 4)タプルの作成
L4 = [x ** 2 for x in range(5)リスト内包表記



全体的にほぼ文字列に対する操作と一緒。

で、実際にやってみる。

>>> len([1, 2, 3, 4]) #長さ
4
>>> [1, 2, 3, 4] + [5, 6, 7, 8] # 連結
[1, 2, 3, 4, 5, 6, 7, 8]
>>> [1,2, 3] * 4 # 繰り返し
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 3 in [1, 2, 3] # 要素が含まれているか
True
>>> 0 in [1, 2, 3]
False
>>>
>>> for x in [1, 2, 3] : print x # ループ
...
1
2
3
>>>
>>> str([1,2,3]) # 文字列へ変換
'[1, 2, 3]' # (list->string '(1 2 3))な感じ??
>>> [1,2,3] + list("456") # リストと文字列の連結。結果はリスト。
[1, 2, 3, '4', '5', '6'] # (append '(1 2 3) (string->list "456"))な感じ??


ふむ。だいたい分かった。


リストの中にリストを入れられるので、2次元配列でも3次元配列でも可能。
2次元配列の例は以下のとおり。

>>> L1 = [[1,2,3],[4,5,6]]
>>> L1
[[1, 2, 3], [4, 5, 6]]
>>> L1[1][1]
5
>>> L1[0][0]
1
>>>

上記のように[][]で要素を指定する。

リストの要素を削除するにはdel演算子を使えば良いらしい。


>>> L1 = [1,2,3,4]
>>> L1
[1, 2, 3, 4]
>>> del L1[3]
>>> L1
[1, 2, 3]
>>>


たとえば、ある特定の範囲を削除するにはスライシングとdelを使用する。

>>> L1 = [1,2,3,4,5]
>>> del L1[3:]
>>> L1
[1, 2, 3]


また上記の別のやり方。

>>> L1 = [1,2,3,4,5]
>>> L1[3:] = []
>>> L1
[1, 2, 3]
>>>

と削除対象がスライシングの場合空リスト([])を代入すると同じことになる。


まとめ

  • リストの基本的操作をマスターした。
  • リストはオブジェクトリファレンスの配列。
  • mutableな属性をもつため、要素を直接編集できる。
  • リストは「シーケンス」カテゴリ。よって文字列操作とほぼ同じ操作で扱える。
ほっほぅ。


[mod_chxj][携帯] POSTされてきたデータのコード変換 - マッチングテーブル定義作成(xml) au編

auの定義は以下。


<ezweb2imode>
<set>
<no>1</no>
<ezweb>
<sjis-hex>F659</sjis-hex>
<utf8-hex>eebd99</utf-hex>
</ezweb>
<imode>
<no>220</no>
</imode>
</set>

・・・略・・・

<set>
<no>2</no>
<ezweb>
<sjis-hex>F65A</sjis-hex>
<utf8-hex>eebd9a</utf-hex>
</ezweb>
<imode>
<no>158</no>
</imode>
</set>
</ezweb2imode>



つまるところ、SJISコードかUTF-8コードからiModeの絵文字を取得できれば良いので、
上記の感じになるかと。


ううむ。sxmlで書いたら面白いかしら。

[mod_chxj][携帯] POSTされてきたデータのコード変換 - 変換ルーチン概念設計

auだけ実装してみようと思うので、変換ルーチンの概念設計をやってしまう。

方針は以下な感じ。

  1. クライアント端末の文字コードを取得
  2. クライアント端末の機種情報取得
  3. サーバサイドの文字コードを取得
  4. POST内容をurldecode
  5. POST内容を走査し、絵文字を見つける。
  6. クライアントがauの場合、見つけた絵文字をezweb→imodeマッチングテーブルを参照しimode用絵文字に変換。
  7. クライアントがimodeの場合、見つけた絵文字を何もせずパス。
  8. クライアントがSoftBankの場合、見つけた絵文字をSoftBank→imodeマッチングテーブルを参照し、imode用絵文字に変換。
  9. 結果をurlencode
  10. サーバサイドへパス。
・・・結構面倒そう。

さて、まずはマッチングテーブルを作成しなくてはならない。
ezweb→imodeマッチングテーブルとSoftBank→imodeマッチングテーブル。

またウノウさまからいただいてSchemeでごにょごにょする予定。

で、今考える作業手順は以下のとおり。
  1. マッチングテーブルの設計
  2. マッチングテーブル定義作成(xml)
  3. マッチングルーチン作成
  4. マッチングルーチンを使用した変換ルーチン作成
  5. 完了。
さっそくやってみる。



2008年1月27日日曜日

[mod_chxj][携帯]

POSTされてくるコードをチェックしてみる。

au端末


端末側がUTF-8だった場合
「晴れ」絵文字==> 「%8F%E4%D1」
==> UTF8コード

端末側がSJISだった場合
「晴れ」絵文字==>「%f6%60」
==> SJISコード

SoftBank端末

端末側がSJISだった場合
「男の子」絵文字 ==>「%1B%24G%21%0F」
==> ウェブコード

端末側がUTF8だった場合
「男の子」絵文字 ==>「=%8F%D9%D1」
==> UTF8のコード

DoCoMo端末

端末側がSJISだった場合
「晴れ」絵文字 ==> 「%F8%9F」
==> SJISコード

端末側がUTF8だった場合
「晴れ」絵文字==>「%EE%98%BE」
==>UTF-8コード


それぞれ広く知れ渡っているとおりぽい。

では、早速機能追加してみる。



[mod_chxj][携帯] UTF-8をちゃんと判別する

さっきコミットしたが、UTF-8の文書の場合の絵文字変換はまだちゃんとしていない。

というのは、UTF-8の1文字のバイト数を暫定的に2バイトづつとしたままだからである。
ちゃんと直さないといけないので書いておく。

UTF-8で1文字のバイト数の出し方


if ((0x80 & 第1バイト目) == 0)
このときは1文字1バイト
else if ((0xe0 & 第1バイト目) == 0xc0)
このときは1文字2バイト
else if ((0xf0 & 第1バイト目) == 0xe0)
このときは1文字3バイト
else if ((0xf8 & 第1バイト目) == 0xf0)
このときは1文字4バイト
else if ((0xc0 & 第1バイト目) == 0x80)
このときは第1バイト目じゃなくて実は第2バイト目以降のバイト



って感じー


というか、全然ダメ。
EUC-JPのときも考慮できていなかったのでこれから修正す。

できた。。