Hatena::ブログ(Diary)

Mattari Memo RSSフィード

2010/03/01

diveintopython 6章読書メモ

このメモは、diveintopythonの日本語訳を読んで、個人的にまとめたものです。

個人的に理解した内容なので劣化している部分があると思います。

はじまりはじまり

5章から1ヶ月放置していて若干抜けてます。

何となくやり方を変えて、基本的な説明と、気になったことの記録程度にします。

あんまり長いとキーボード打つのも面倒ですし


前回まではクラスを重点的にやりました。5と6章まででfileinfo.py の解説を網羅するそうです。

6章は、ファイルの取り扱いと、それに伴って必要になる例外処理のお話。fileinfo.pyの解説ではlistDirectory関数の解説を行い全てをまとめてる。

例外処理

Chapter 6. 例外とファイル操作

python例外処理は、try...exceptブロック(文)

try節で例外があるだろう処理を入れて、あるだろう例外をexcept節で指定。

その他に使える節はfinally文、raise文、else文

finally文では、例外が発生してもしなくても最終的に動く節。

else文はif文のと同じ意味。ここでは例外が起こった場合と起こらない場合を分けたときにこれを使う

(ここでの例ではファイルの読み込みとクローズ処理をfinally節で実装してる。他方else節を使っている人もいました。どっちのほうがいいのかな?)

Python: ファイル読み込み時の例外の扱い例 - try、except、else、finallyブロック - Yukun's Blog

raise文はここでは説明がない。pythonのドキュメントでは例外を強制的に発生させるものらしい。

8. エラーと例外

最後に文なのでコロンを忘れずに。

try :
 fo = open("/file/to/path/hogehoge","r")
except IOError :
 print "hogehoge not open error!"

ファイルのオープンや読み込み書き込みは、例外がつきもの。

別のプログラムによってそのファイルがいきなり消えたり、誰か別のユーザが書き込んだりと(排他処理により)自分の持ち物でない可能性がある。

try節で例外がでそうな内容を入れて、exceptででた例外についての処理を書く。exceptの例外指定は複数可能、もちろん例外に対して処理を分けるために複数のexceptも書ける。


例外とは、プログラムに組み込んだ内容から想定以外の事柄の事をいい基本的にエラーが出る物。そのとおりに利用するほかにも、それを利用して他の方法を行う場合がある。特定の環境での代替処理とか。

6.1.1. 他の目的で例外を使用する

##Example 6.2. プラットフォーム固有の機能をサポートする
  # getpass という名前に適当な関数を割り当てる
  try:
      import                      termios, TERMIOS
  except ImportError:
      try:
          import                            msvcrt
      except ImportError:
          try:
              from  EasyDialogsimport  AskPassword
          except ImportError:
                         getpass = default_getpass
          else                                   :
              getpass = AskPassword
      else:
          getpass = win_getpass
  else:
      getpass = unix_getpass

ファイル入出力

6.2. Working with File Objects

もう例外のところで出てきているopen関数は、開きたいファイルパスを引数にして実行するとファイルオブジェクトを返す関数。そのファイルオブジェクトを使って、読み込んだり中身のプロパティを調べたりする。

open関数引数はファイルパス以外にも、オプションとしてファイルのモード(読み込み、書き込み、テキストかバイナリか)、バッファリングパラメータの指定が行える。モードはとりあえず大事ですね。


ファイルを開いたら読み込む。読み込みには、tellとseekメソッドを使ってファイルのどの位置を読みたいか指定して読み込むとか、全部読み込むreadメソッドや、改行がある場合は1行ごと読み込めるreadlineメソッドとか。

3.9 ファイルオブジェクト

ファイルを書き込む時は、writeメソッドを使う。ファイルモードが'w'か'a'でないとダメ。wは上書きしてaは追記できる。

ファイルを閉じるときはcloseメソッドを使う。

ファイルを開いている間は、そのプログラムが利用中の事だから他のプログラム排他的処理により使えない。ので開放する必要がある。メソッドを使い開放すると、ファイルオブジェクト側では読み込めないことがわかる。

forループの説明

6.3. Iterating with for Loops

pythonのfor文は、リストの中身だけ繰り返す。数字指定のカウンタとかは普通はしないらしい。はじめて知ったときは衝撃的(他の言語にfor each文があればそれに似ている。)

しかし、リストの中身をそのまま使えるのでわかるととても便利。

##Example 6.8.  for ループの紹介
 >>>li = ['a' ,'b' ,'e']
 >>>for  sin li:        
     ...print s         
a
b
e
 >>>print "\n".join(li)  #リスト読み込み
a
b
e

ちなみに、カウンタをやるなら、range関数を使う。range関数は数値のリストを作成してくれるので、実質的にそうなる。


##Example 6.9. シンプルなカウンタ
 >>>for  iin range(5):             #range(5)を動かすと[1,2,3,4,5]が作られる
     ...print i
0
1
2
3
4
 >>>li = ['a' ,'b' ,'c' ,'d' ,'e']
 >>>for  iin range(len(li)):       #わざわざリスト内の個数を数えてリストの位置指定で出す必要は無い。
     ...print li[i]
a
b
c
d
e

forループ(もといリストのマップ)はあらゆるものを繰り返す。辞書も使えるが例にある。

というか辞書が使えたらだいたいの格納されている事柄は何でも出力できる事になって面白い。

(例えばdir関数モジュール関数やメソッドの一覧が見れるけどあれは辞書なので、一覧出力とかも普通にできる。

dir()関数 - バリケンのPython日記 - pythonグループ→さらに便利→Coffee and Ashtray: pythonにsee()を入れる

6.10の例では、OS環境変数の一覧を出している。for文とリストマップの例がありどちらも出力結果は同じに見える。


forループの使いどころとしては、取り出したリストの内容を関数を使って処理させたい場合なんかだろうか。

リスト読み込みは結果としてリストを返すし、わざわざリストを作る必要がない場合はこれを使う方が良いのかな。

sysモジュールを使う

6.4. sys モジュールを使用する

sysモジュールとは、OSのシステムレベルの情報や行える操作をまとめたモジュールのこと、多分(おい

再帰の深さの最大値まで決まってるなんてのはしなかった!

sys.modulesの中には現在利用されているモジュールの一覧がある。

#Example 6.13.  sysモジュールを使用する
 >>>import fileinfo         1
 >>>print '\n'.join(sys.modules.keys())
win32api
os.path
os
fileinfo
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
 >>>fileinfo
<module 'fileinfo' from 'fileinfo.pyc'>
 >>>sys.modules["fileinfo"] 2
<module 'fileinfo' from 'fileinfo.pyc'>

sys.modulesは辞書になっている。値がモジュールリファレンスでキーが名前なので、キーを指定するとモジュールリファレンスが手に入る。

これをこの章では、MP3以外の定義をしてあるFileinfoクラスを探すために使う。次のosモジュールを使うとそれが実現するとか。

__module__クラス属性とは

組み込みのクラス属性、クラスが定義されているモジュールの名前が出てくる。

つまり、あるクラスに__module__属性を参照すると、そのクラスのモジュール名が分かる。モジュールがファイル名と同じなら追跡が楽になるかもしれない。

os.pathモジュールを使う

6.5. Working with Directories

ここでは、os.pathモジュールでファイルパスの操作を行う。プラットフォームに依存するモジュールだがこれを使うことで、プラットフォーム固有の違いを隠喩してる。

pathというだけにファイルパスの操作を行える。ファイルのフルパスからファイルのパスとファイル名を分離したり、パスとファイル名を統合したり。

今回で大事なところは、拡張子も分離出来る点。これを使って、特定の拡張子の定義をしてあるFileinfoクラスを探す方法を実装している。

これを使うとファイルパスをいじるのが大変楽に思う。こちらが手入力するパスなんかは気を遣うかもしれない。

最後にまとめてる

というわけで、上の解説から今回のfileinfo.py の解説を見てみる。

Example 6.6. MP3FileInfo 内のファイルオブジェクト

        try                                :
             fsock = open(filename,"rb" , 0)
            try                           :
                         fsock.seek(-128, 2)
                   tagdata = fsock.read(128)
            finally                        :
                              fsock.close()
            .
            .
            .
        except                      IOError:
            pass         

MP3FileInfoのファイルオブジェクトを見ると、なんてことない普通のファイル操作。

seek(-128, 2)でmp3ファイルのタグ情報の位置へ移動(どうやらタグ情報はデータの後ろに載っているらしい)、read(128)でそのタグ情報を読み込む。この間で例外をキャッチしたらこの処理自体をパスする。

Example 6.11. MP3FileInfo 内の for ループ

    .
    .
    .
def stripnulls(data):
    "strip whitespace and nulls"
    return data.replace("\00" ,"").strip()
    .
    .
    .
    tagDataMap = {"title"   : ( 3, 33, stripnulls),
                  "artist"  : ( 33, 63, stripnulls),
                  "album"   : ( 63, 93, stripnulls),
                  "year"    : ( 93, 97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"                                  : (127, 128, ord)}
    .
    .
    .
            if  tagdata[:3] =="TAG":
                for  tag, (start, end, parseFunc)in  self.tagDataMap.items():
                                    self[tag] = parseFunc(tagdata[start:end])

tagDataMapは、タグ情報のどの部分がどの項目(アーティストとかアルバムとか)を示すマップを作ってる。辞書の値がタプルで3番目が解析するための関数の名前になってる。

そのマップを下のロジックに取り込む。

まずfor文でマップ無いのキーと辞書をタプルで分離。paeseFuncには関数名が入り、これを関数として実行することができる。

次に、リストを継承したクラスの中に解析関数で実行した内容を入れる。中身はstart:endでわかるように、タグ情報をマップの数値でスライスして、parseFuncにある関数名の関数を実行している。

stripnullsは、"\00"を消してstrip関数で先頭と松尾部分の空白文字の除去を行う。

・・・あれ、strip関数ってとっても便利ですね。今度コードを書くときに早速使ってみよう。

3.6.1 文字列メソッド


Listdictionary関数詳細

今回のfileinfo.py では、MP3以外のファイルもメタ(タグ)情報も対応出来る仕組みを作ってる。それがlistDirectory関数

Example 6.15. fileinfo.pyないの sys モジュール

    def getFileInfoClass       (filename, module=sys.modules[FileInfo.__module__]) #1
        "get file info class from filename extension"                             
         subclass ="%sFileInfo"         % os.path.splitext(filename)[1].upper()[1:] #2
        return  hasattr(module, subclass)and  getattr(module, subclass)or  FileInfo #3
  • #1

このgetFileInfoClass関数では、与えられたファイル名(ファイルのフルパスではなくて、パスを取り除いてるらしい)と、オプションにmodule変数引数を持っている。

moduleのデフォルトには、sys.modulesからFileInfoクラス内のモジュール名を入れている。と言ってもこれはオプションで、実際には使っていないことが後で分かる。あくまで定数扱い

  • #2

次に、いわゆる文字列整形が使われている。%sには、os.path.splitext関数により分離されたfilenameの拡張子が入れられている。

その後にupperメソッドは小文字を大文字に変換するメソッド。さらに文字列をスライスして拡張子の大文字だけを残してる。

hoge_audio.mp3というファイル名が来たら、ここのsubclassは"MP3FileInfo"となるはず。"huga_huga.txt"ならTXTFileInfo

  • #3

最後に三項演算子っぽい実装になってる。といっても実際にはgetattrを使ってmodule内のメソッドを探しに行ってる。

今回の場合は、modules(このモジュール内のリファレンス一覧)からsubclassを探して、リファレンスを得ると言うこと。

拡張子が.mp3ならこのモジュール(fileinfo.py)内のMP3fileinfoクラスを参照していることになる。

hasattrは、subclassがそのモジュールに有るか確認を取るために入れているらしい。三項演算子だから、hasattrで存在を確認したらgetattrを実行、そうでないならFileInfoクラスを使うことにしてある。

2.1 組み込み関数のhasattrを参考

ほかのプログラムに応用するならFileInfoの部分をモジュール内の適当なクラスにでもすればいいのかな。

Example 6.19. fileinfo.py 内の辞書をリストする

def listDirectory(directory, fileExtList):
    "get list of file info objects for files of particular extensions" 
    fileList = [os.path.normcase(f)
                for  f in os.listdir(directory)] #1 2
     fileList = [os.path.join(directory, f) for f in fileList
                if  os.path.splitext(f)[1]in   fileExtList] #3 4 5

6.18の上にある処理の話しで、2回のリスト読み込みで指定したディレクトリ内の特定のファイルのリストを作成している。

  • #1,2

dictionary(と言う指定したディレクトリ)より、os.listdir()でディレクトリ内の全てのファイルとフォルダのリストを返して、os.path.normcase関数でパスの大文字小文字をシステムの標準にししたリストをfileListに入れてる。パスを扱いやすくしているというイメージかな。

  • #3,4,5

次でfileExtList(という扱いたいファイルの拡張子のリスト)を使ってリストフィルタリングをして、ファイルのフルパスに戻したリストを格納してる。

これで、対象のディレクトリ内から指定した拡張子のファイルだけを集めた段階になる。

listDirectory関数を見る

def listDirectory(directory, fileExtList):
    "get list of file info objects for files of particular extensions" 
    fileList = [os.path.normcase(f)
                for  f in os.listdir(directory)] 
     fileList = [os.path.join(directory, f)
                for f in fileList
                 if  os.path.splitext(f)[1]in   fileExtList] 
    def getFileInfoClass       (filename, module=sys.modules[FileInfo.__module__]) 
        "get file info class from filename extension"                             
         subclass ="%sFileInfo"         % os.path.splitext(filename)[1].upper()[1:] 
        return  hasattr(module, subclass)and  getattr(module, subclass)or  FileInfo 
    return  [getFileInfoClass(f)(f) for f in fileList] #1
  • #1

この関数の最後に、ファイルごとのメタ情報(の辞書)をリストにして返してる。

getFileInfoClassでファイル名を引数指定すると、そのファイルにあったメタ情報解析クラスが見つかり、

さらに(f)でクラスの引数としてファイル名を与えると、結果としてメタ情報を解析したインスタンスインスタンス自体が辞書)が返ってきて、リスト化されてる。

これで全て解説されました!

長かった・・・(自分がサボってただけ)

最後に見直してみる。

fileinfo.py

このモジュールの最後に、pythonコマンドで実行された場合が書かれている。

if __name__="__main__"がコマンドでの実行時の命令だが、ここではディレクトリ拡張子が指定されている。デフォルトでの指定らしい。

もしコマンドの引数ディレクトリを指定した場合の書き方としてはこんな感じ?(何もチェックしていないけど)

Python: コマンドライン引数の取得 - sys.argv変数 - Yukun's Blog より

.
.
.
if  __name__ =="__main__":
    argvs = sys.argv
    argc = len(argvs)
    print(u"引数にディレクトリ先を指定することで実行されます。\n====")
    if argc != 2 :
		print u"Usage: python %s directory" % argvs[0]
		quit()

    for  infoin listDirectory((argvs[1]), [".mp3"]):
        print "\n".join(["%s=%s"  % (k, v)for  k, vin info.items()])

感想として

ファイルに書き出してもおもしろいかもしれませんね。実用的で本当にモジュールに組み込んでも良さそうなじゃないかと思ったところです。

次は7章ですね。正規表現だ!!

2010/02/04

勉強メモ:Cのポインタの意味を考え直す

これは本当にメモ


Cのポインタって結局なんなんだろうなって考えていていまいちまとまらない。

構造体にポインタがある理由は何となく、構造体の枠組みを複製する際に、複製したメンバ(構造体内の変数でいいっけね?)にアクセスするためには、ポインタを使ってアドレスを割り出さないといけないって意味があるのかなと思ったから。

あと、ドット演算子とアロー演算子の違いは、ドット演算子は構造体変数自体からメンバにアクセスする際には必要で、アロー演算子は構造体のアドレス変数からメンバにアクセスするために必要ってことかな。


結局ポインタという機能は本当はいらないのかもしれないけど、より自由にメモリにアクセスするためには、メモリのアドレスを直接参照出来る機能があるといいって話だったのかな。そうするとCってやっぱり上級者向けなんだなーとも感じる。


あとポインタを割り出すってやっぱり何か計算してるのかな。変数名とポインタの関係ってどこかメモリ上にあるのかと思ってたけど、どうなんだろう、そうなのかな?

2009/12/20

ファイルのフルパスをパスとファイル名と拡張子を分ける時に格納する変数名の規則決め

ファイルを扱うプログラムを作るときに,ファイルのフルパスからいろいろ分割して変数に格納することはしょっちゅう.変数名を決めておかないととたんにわからなくなるのでちょっと悩んで決めておいた.

自分で思いついたものをつけつつ,参考にいろいろ見てたら結局diveintopythonのまとめになってた.

ファイルのフルパス:filepath
ファイルのパス:dirname
ファイル名(拡張子とセット):filename
ファイルの名前:shoutname
拡張子:fileext

リストなどの複数系なら複数系の変数名にすればいい.(filenames

最初,フルパスをfilefullpathにしてみたけどわかりやすいけど長いからやめた.絶対パスとか相対パスも英訳で問題ないだろうか.

これが一般的によく使われるものなのかは知らない.

2009/12/02

diveintopython 5章読書メモ

読書メモで,本家なんかに書いてあるコードは書かずに,試したものとかを書いておく.本家コードは必要以外リンクとして残すし残さないこともある.面倒がりな人間.

ぶっちゃけただの脳内メモなので,何となく見ている人に向けて書いてあるにしては,人のためにはならんはず.


5章始まる

オブジェクト指向ということで,なまじわかってたつもりでしたが.理解し切れていない部分があると何か読みにくかったんだよなあ.

今回のお題は,フォルダの中にあるmp3ファイルのID3v1.1タグの内容を出力するプログラム.結構実用的.ID3v2.*に対応できたらもっとおもしろそう.(実はもっと汎用的で,ほかのファイルフォーマットのメタデータの配置位置を定義できれば何でも対応できるらしい,6章で実態がわかります.)

ちなみにこのプログラム自体の解説としては6章に続くらしいです.

from module importを使ったモジュールのインポート

5.2. Importing Modules Using from module import

import moduleはモジュール自体をインポートしてその下にある属性をドットで使うというもの.

from module importをすると,ほしい属性だけインポートできる.その際にモジュール名.属性 とかやらなくていい.属性の名前の指定で動く.

詳しくはNoteを参考に

(あとでやるかもしれないけど,asも使えて別名で使うこともできる.たくさんドットで区切ったような複雑なパッケージにはこれが有効)

Pythonのモジュールインポートのしくみ

import moduleとの使い分けとしては,頻繁に使って名前が混同しない場合はfrom〜でいいし,名前が混同しそうならimport moduleでモジュール名で分けてもよい.

これもスタイルの問題なので,コードを見てたら両方のやり方を見るだろうとのこと.

クラスの話し

5.3. Defining Classes

classで定義する.引数も使える.引数なしもできる.doc stringは利用すべき.

class testclass:
"""this class is hogehoge"""
  pass

継承したりもできる.継承元を引数に入れておく

from UserDictimport UserDict

sclass FileInfo (UserDict):

5.3. Defining Classes

たとえばこれはUserDictというクラスを継承した.このクラスは継承したものがあたかも辞書っぽく使えるようになるクラス.


初期化は,def __init__で定義.init(イニト)はイニシャライズで初期化です.特別なメソッドの位置だったと思う.

コンストラクタ(構築子,インスタンスが作成された時に初期化するときに使うメソッド)のように動くが,そのように定義しただけで,初期化する前にインスタンスは作成されてるからコンストラクタとはいえない.けどそんな風に動く.

えーと間違えてるかもしれないけど,クラス定義にしている引数継承に使っているので,クラス自体の引数指定は__init__を使う.コンストラクタはそういうものらしい.

以下を参照

もちろん、より大きな柔軟性を持たせるために、__init__() メソッドに複数の引数をもたせることができます。 その場合、クラスのインスタンス生成操作に渡された引数は __init__() に渡されます。例えば以下のように:

>>> class Complex:

... def __init__(self, realpart, imagpart):

... self.r = realpart

... self.i = imagpart

...

>>> x = Complex(3.0, -4.5)

>>> x.r, x.i

(3.0, -4.5)

9. クラス

class FileInfo(UserDict):

"store file metadata"

def __init__(self, filename=None):

UserDict.__init__(self) 1

self["name" ] = filename 2 3

5.3. Defining Classes

Fileinfoクラスでは,コメント通りにファイルのメタデータを貯めることらしい.

最初の__init__でUserDictの__init__を呼び出してる.

この際の引数self(というか__init__のselfのこと)はクラスから作ったインスタンスのことをいってる.クラス自身ではない.

Pythonではインスタンス内でインスタンス内のメソッド,属性(それをデータ属性と言われる)を使うときにはselfを指定する必要がある.というのも,クラスが呼び出される時と,実際にインスタンスを使っているときとは挙動は違うらしい.

これ以上はクラスに詳しくないので説明できなかった.後でクラスとしての参照とインスタントしての参照の話しがあるっぽいので何となくわかるけど,その二つの参照を分けるときにこの仕組みを使っているらしい.らしい?


ここの方のエントリーで紹介されている通り,Rubyの説明がしっくりきている.

Pythonのクラスのselfの意味 - 牌語備忘録

現在の自分自身の参照という意味を込めてself.


戻って1のこと.UserDict.__init__は継承したUserDictの__init__を呼び出してる.5.3.2でいってるけど明示的に呼び出す必要が有るらしい.Pythonの仕様らしい.

2でUserDictがどのように動くを表したといってるけど,辞書っぽくnameキーにfilenameが入ってる.辞書っぽい振る舞いなのであーそうなのか程度.

3の説明として,__init__は返値は返さない.返す必要も無いのかもしれない?と感想を持った.


5.4. Instantiating Classes

インスタンスを作ると,__class__という属性でクラスのメタデータ?クラスの情報ととらえてる.

__doc__はdoc string.あるクラスから作ったインスタンスが複数有っても,そのdoc strringは同じものを共有するようになってる.



ガベージコレクション(GC)

5.4.1. ガベージコレクション

Pythonはそれに優れているらしい.

ガベージコレクションとはプログラムが動的にメモリを確保してくれる機能.使わなくなった領域(今回だとオブジェクトインスタンス内)に割り当てた領域)が有ると自動的にメモリを解放してくれる.解放というか使わないとわかったら破棄して使えるようにする.

実際に例でメモリリークを試みてる.

ある関数変数インスタンスを代入してる.その関数内のローカル変数で,fはそのまま残されてる.

次の100回実行されると,そのインスタンスが残るんじゃないかと言われている.が結果は残らない.


なんだかデフォルトなのでありがたみが感じられないような雰囲気.あまりほかの言語の経験も無いのもあって.

Pythonのドキュメントにある1.10 参照カウント法にて,Cだmallocとかfreeでやることが,Pythonでは自動的に見てくれてる.考える必要がある程度減るのは助かることだろう.


辞書っぽいUserDictクラス

5.5. Exploring UserDict: A Wrapper Class

5.5からUsreDictの説明がある.ラッパークラスということで,辞書っぽく見せてるというのはこういう仕組みだと言うことが書かれてる.

diveintopythonの日本語訳だと読んでても頭に入ってこなかった気がして,diveintopythonの超訳版を書かれているid:hamatzさんのDive Into Python (4日目) - 暗号、数学、時々プログラミングを見させてもらった.感謝.


ここでの説明はラッパークラスの紹介が基本で,その実現に特殊メソッドがあるとのことだと思う.

(その前に辞書で行うcopy()とかclear()の)通常メソッドの説明もされてる.copyを実現する時の注意点,クラスとメソッドの参照の違いなどがあるので注意とか.

特殊メソッドは特定の状況や特定の構文が呼ばれると実行されるメソッド.

UserDictなら,test["no1"]の中身を得るような構文をあたかも簡単に実現しているのには,その構文は__getitem__を呼び出し書かれている処理をしているから.

def __getitem__ (self, key):

return self.data[key]

>>>f = fileinfo.FileInfo("/music/_singles/kairo.mp3")

>>>f

{'name':'/music/_singles/kairo.mp3'}

>>>f.__getitem__("name") 1

'/music/_singles/kairo.mp3'

>>>f["name"] 2

'/music/_singles/kairo.mp3'

5.6. Special Class Methods

特殊メソッドを使うと,そのメソッドが実現する構文を簡単(?)に定義して利用することができる.いろいろあるから後で見るのも良さそう.

そもそも,python2.2以降は,組み込みデータ型の辞書である,dictを直接継承できるらしい.どちらを使うかはスタイルの問題なのかその辺は定かではないけど.

ただ単純にこうラッパーなクラスを作って実現している実例だしとてもおもしろい.


特別なクラスメソッド

5.6. Special Class Methods

では実際に今回のお題ではどう扱っているか.

def __setitem__ (self, key, item):1

if key =="name" and item:2

self.__parse(item)3

FileInfo.__setitem__(self, key, item)4

5.6. Special Class Methods

コード内の__setitem__は先祖のメソッド(UserDict.__setitem__)をオーバーライド(上書き)していて,そこに仕掛けを埋め込んでる.

keyが"name"だった場合とitemがある場合(andなので両方ともでTrueなら)インスタンス内の__parseを実行して,親メソッドのFileinfoの__setitem__を実行する.

このときの4は,FileInfo内では何もされてないのでさらに親のUserDictへ探しに行って呼び出してる.


それで,これが実際に動くとどうなるかが,Example 5.15に書かれている.

fileinfoのインスタンス作成時にfilenameが"name"キーの辞書っぽくなり,さらに値が追加されているので__parseが動いて結果が出てくる.結果はタグの内容が辞書にされているようだ.


高度な特殊クラスメソッド

5.7. Advanced Special Class Methods

次の項目はさらに特殊なメソッドの紹介がある.UserDictの中身をさらに見ているけど,辞書を文字列にしたり,インスタンスの比較,オブジェクトの長さ,辞書のアイテムの削除等.

ラッパークラス内での特殊メソッドの紹介だったけど,特殊メソッド自体はどのクラスでも使えるらしい.比較したときには何を比較させればいいのか,長さを見たときはどの長さを見ればいいのかとか.

そのほかにも特殊にカバーされたメソッドを定義することはできるそうで,後々に紹介されるとのこと.


データ属性,クラス属性

5.8. Introducing Class Attributes

データ属性とは,インスタンス内の属性の意味だった.クラス属性はクラスに内蔵された属性のこと.

同じものをインスタンス内で何度定義するなら最初から入れておくのもよい.フォーマットの解析に必要な値とか.

Example 5.17で,ID3v1.0のmp3タグのデータマップを表してる.たぶんmp3ファイルの頭にあるヘッダデータみたいなものを読むときに使う数字群だろう(と予測してる.まだ6章見てない・・・)


クラス属性をインスタンス側で変更すると,クラス自体の値も変わってる.同じクラスを継承したインスタンス側も共有される.

さしずめ定数ともいえるけど変更は可能.Pythonのお約束?

プライベート関数

プライベート要素の概念が言われている.引用すると,

多くの言語のように Python はプライベート要素の概念があります。

* プライベート関数は、そのモジュールの外からコールすることができません。

* プライベートメソッドは、そのクラスのの外からコールすることができません

* プライベート属性は、そのクラスの外からアクセスすることができません

多くの言語とは違って、 Python関数、メソッド、属性がプライベートかパブリックのどちらであるかは、名前によって完全に分けられます。

5.9. Private Functions

とのこと.

さきほどのMP3FileInfoで,__parseが出てきたが,これがプライベートの意味.アンダーバー二つで始めるとそう定義できる.

ただ,特殊メソッドはアンダーバー2つで始まり2つで終わる.慣例らしいので,従わなくてもいいけど混乱するだろうからやめた方がよいとの.

Example 5.19では,メソッドのコールを試みてるが失敗してる.とはいえできない訳ではないが行わない方がよいとの.

ところで__parseをプライベートにする理由はなんだろうと.不用意に呼ばせないためとか?


以上終わり

次は6章.コードの続きを解説.

2009/10/07

Mac OS Xのインターネットアイコンのチュートリアルをinkscapeで再現

暇だったので取り組んでみたらえらく疲れた。多分photoshopは楽なんだろうな(GIMPもそうかな?

元ネタよりMac OS Xの設定?画面のインターネットアイコンをinkscapeで再現しました。

元ネタ

apple好きにはたまらないapple風のボタンやメニュー作成チュートリアル集:phpspot開発日誌

20 Apple-inspired Tutorials for Practice Web Designers

How To Draw A Mac Internet Globe Icon — Flyosity: Mac & iPhone Interface Design


手順なんか作る気にならなかったのでファイルだけあげておきました。

所詮素人なので見苦しい部分がありますがお許しを。

http://dl.getdropbox.com/u/203922/macosx_internet_icon_saigen.svg


完成品

完成度は低めです。色に納得いかん。

f:id:piropati:20091007125029p:image

  • 背景を白色にしました

多分再現してみている人はたくさんいるんだろうなあ。