poplibモジュール

受信したメールを処理するプログラムをpythonで書きたいので、
まずは poplibモジュールの勉強。参考にさせていただいたのは
http://nagosui.org:8080/Nagosui/COREBlog2/categories/learning-python/cbcategory_view?b_start:int=9&-C=
のページです。
このモジュールはPOP3クラスを提供してくれる。
まずはメールサーバへのログイン。POP3オブジェクトを作ってuser(),pass_()メソッドを使えばよいみたい。

>>> import poplib
>>> p = poplib.POP3("mail.xxxx.co.jp")  #サーバ名を指定する。第2引数のportを省略すると
>>> p.user("指定のID")                     POP3標準のポート(110)が使われる。
'+OK Password required for xxxx.'
>>> p.pass_("指定のpass")
'+OK xxxx has 1 visible message (0 hidden) in 1744 octets.'

user()メソッドはパスワード要求を、pass_()メソッドはメッセージ数とメールボックスサイズを返してくれるみたい。
つづいてメールを取り出すにはretr()メソッドを使えばよいみたい。引数には何番目のメッセージを取り出すのかを指定する。

>>> p.retr(1)
('+OK 1744 octets', ['Return-Path: <xxxx@xxxx.co.jp>', 'Delivered-
To: xxxx@xxxxx.co.jp', 'Received: (qmail xxxx invoked from network
); 26 Dec 2008 17:17:57 +0900', ・・・・・・, '------=_NextPart_xx
xx--', '', ''], 1744)

上の結果は省略した部分が多いけど、retr()メソッドを使って返ってくるのは3つの要素を持ったタプルでその内容は、
0番目の要素:サーバからの応答文字列
1番目の要素:メール本体の内容が1行ごとに分割されて含まれたリスト
2番目の要素:メッセージのサイズ
となるみたい。だからこの1番目の要素を取り出せばメッセージの内容が取得できるわけだから、

>>> p_message = p.retr(1)[1]

とすれば良いわけだ。
サーバとの接続を切断するにはquit()メソッドを使えばよいみたいで、

>>> p.quit()
'+OK Pop server at mail.xxxx.co.jp signing off.'

Factory Methodパターン

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターン
書いてみる。今回の題材はFactory Methodパターン。
前回書いたTemplate Methodパターンはスーパークラスで処理の大枠を作って、サブクラスで
具体的処理を決定するというものだった。
このパターンをインスタンスをつくる場面に適用したものがFactory Methodパターンというものみたい。
今回のサンプルプログラム(factory_method.py)はIDカードを作る工場を仮定したもの。
それでは書いてみる。
最初はProductクラス

class Product(object):
    def use(self):
        pass

ここは「製品」を表現したクラス。Javaで書いたときの抽象メソッドuseが宣言されているので、pythonでもuseメソッドの宣言のみ。
次はFactoryクラス

class Factory(object):
    def create(self, owner):
        p = self.createProduct(owner)
        self.registerProduct(p)
        return p

    def createProduct(self, owner):
        pass

    def registerProduct(self, product):
        pass

ここではTemplate Methodパターンが使われている。Template Methodパターンって何だったかというと
スーパークラスで処理の大きな枠組みを決めておいて、サブクラスでその具体的処理を決める」だった。
今回に当てはめるとこのクラスは処理の大きな枠組みを規定しているものになる。
具体的な処理が決まっていないcreateProductとregisterProductの両メソッドで「製品を作り」、「登録する」
が実装はサブクラスが担う。
createメソッドではcreateProductとregisterProductの両メソッドを使って「製品」のインスタンスを生成しているわけだ。
Factory Methodパターンではインスタンス生成にTemplate Methodパターンが使われる。
つづいてIDCardクラス

class IDCard(Product):
    def __init__(self, owner):
        self.owner = owner
        print "make %s's card" %(self.owner)

    def use(self):
        print "use %s's card" %(self.owner)

    def getOwner(self):
        return self.owner

ここでは具体的処理を定義している。このクラスはProductクラスのサブクラスとして定義して、コンストラクタを作り、
useメソッドとgetOwnerメソッドを定義。
さらにIDCardFactoryクラス

class IDCardFactory(Factory):
    owners = []
    def createProduct(self, owner):
        return IDCard(owner)

    def registerProduct(self, product):
        self.owners.append(product.getOwner())

    def getOwners(self):
        return owners

このクラスでcreateProductとregisterProductメソッドを実装している。
createProductメソッドはIDCardクラスのインスタンスを生成して「製品を作る」を行っている。
registerProductメソッドはgetOwnerメソッドで得たIDCardのowner(所有者)をリストownersに加えることで
「登録」を行っている。
最後に動作テストを行う部分

factory = IDCardFactory()
card1 = factory.create("Taro")
card2 = factory.create("Ichiro")
card3 = factory.create("Hanako")
card1.use()
card2.use()
card3.use()

IDCardFactoryクラスのインスタンスを作って、createメソッドを使う。IDCardFactoryクラスはFactoryクラスの
サブクラスだからcreateメソッドが使える。createメソッドは「製品」のインスタンスを生成するので、そのインスタンス
対してuseメソッドを使う。IDCardFactoryクラスのインスタンスはIDCardクラスのインスタンスを生成するのでIDCardクラス
で実装されているuseメソッドを適用できることになる。
実際に実行してみると、

C:\works\python\book1>python factory_method.py
make Taro's card
make Ichiro's card
make Hanako's card
use Taro's card
use Ichiro's card
use Hanako's card

インスタンス生成による委譲を利用してTemplate Methodパターンを実現したパターンになるわけか。

Template Methodパターン

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターン
書いてみる。
今回はTemplate Methodパターン。
どんなものかというと、スーパークラスにテンプレートとなるメソッドが定義される。
ただその定義の中ではメソッドは実装されない。
メソッドを実装するのはサブクラスで、そこで具体的な処理が決まるというもの。
異なるサブクラスが異なる実装をすれば、異なる処理が行われけど、処理の大きな流れはスーパークラス
決めたとおりになる。
このように、スーパークラスで処理の大きな枠組みを決めておいて、サブクラスでその具体的処理を決める
デザインパターン
サンプルになっているのは、文字や文字列を5回繰り返して表示するもの(template.py)。
まずはAbstractDisplayクラス

class AbstractDisplay(object):
    def opening(self):
        pass

    def printing(self):
        pass

    def closing(self):
        pass

    def display(self):
        self.opening()     #openingメソッドの呼び出し
        for i in range(5):    #printingメソッドを5回呼び出し
            self.printing()
        self.closing()     #closingメソッドを呼び出し

ここでは「opening」、「printing」、「closing」の3つのメソッドを宣言して、
displayメソッドの中でその具体的な処理が決まっていない3つのメソッドを使っていて、
displayメソッドがテンプレートメソッドになる。
opening,printing,closingメソッドを実装するのはサブクラスが担う。
次はCharDisplayクラス

class CharDisplay(AbstractDisplay):
    def __init__(self, ch):
        self.ch = ch

    def opening(self):
        print "<<",

    def printing(self):
        print self.ch,

    def closing(self):
        print ">>"

ここではAbstractDisplayクラスを継承してopening,printing,closingメソッドを実装している。
つづいてStringDisplayクラス

class StringDisplay(AbstractDisplay):
    def __init__(self, st):
        self.st = st
        self.width = len(self.st)   #文字列の長さを出しておく

    def opening(self):       
        self.printLine()        #このクラスのメソッドprintLineで線を引く

    def printing(self):        
        print "|%s|" %(self.st)    #文字列の前後に"|"を付ける

    def closing(self):
        self.printLine()               #このクラスのメソッドprintLineで線を引く

    def printLine(self):               #printLineメソッドを実装
        print "+",           #枠の角の"+"を表示
        n = 0
        while n < self.width:     #文字列の長さの分の"-"を表示
            print "-",
            n += 1
        print  "+"           #枠の角の"+"を表示

ここでもAbstractDisplayクラスを継承してopening,printing,closingメソッドを実装している。
最後にCharDisplayクラスとStringDisplayクラスのインスタンスを作ってdisplayメソッドを呼ぶ。

d1 = CharDisplay("H")
d2 = StringDisplay("Hello, world.")
d1.display()
d2.display()

d1,d2はAbstractDisplayクラスのサブクラスのインスタンスだから継承したdisplayメソッドが使える。
さて、実行してみると、

C:\works\python\book1>python template.py
<< H H H H H >>
+ - - - - - - - - - - - - - +
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
+ - - - - - - - - - - - - - +

あれ?文字の間にスペースができてしまってる。
どうやらprintを使うと出力直後に空白が一文字出てしまうためみたい。
そこで標準出力への書き出しに print ではなく sys.stdout.write() を使って書き直し。他にも短く書けるところを修正してみた。
修正CharDisplayクラス

import sys
class CharDisplay(AbstractDisplay):
    def __init__(self, ch):
        self.ch = ch

    def opening(self):
        print "<<",

    def printing(self):
        sys.stdout.write(self.ch)

    def closing(self):
        print ">>"

修正StringDisplayクラス

class StringDisplay(AbstractDisplay):
    def __init__(self, st):
        self.st = st
        self.width = len(self.st)

    def opening(self):
        self.printLine()

    def printing(self):
        print "|%s|" %(self.st)

    def closing(self):
        self.printLine()

    def printLine(self):
        sys.stdout.write("".join(("+","-"*self.width,"+\n")))

それでは実行してみると、

C:\works\python\book1>python template.py
<<HHHHH>>
+-------------+
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
|Hello, world.|
+-------------+

きれいに収まった。
同じメソッドを使っているけど実際の動作は個々のクラスのCharDisplayとStringDisplay
で決まっているわけだ。

Adapterパターン

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターン
書いてみる。
今回はAdapterパターンがテーマで、与えられた文字列を(Hello)のように表示したり、*Hello*のように表示するプログラム。
クラスによるパターン(継承を使う)とインスタンスによるパターン(委譲を使う)が
示されている。
まずは継承を使ったパターン(adapterk.py)から。
最初はBannerクラス

class Banner(object):
    def __init__(self, word):
        self.word = word

    def showWithParen(self):
        print "(%s)" %(self.word)

    def showWithAster(self):
        print "*%s*" %(self.word)

ここでは文字列をカッコに入れて表示するshowWithParenメソッドと文字列の前後に*を付けて表示する
showWithAsterメソッドをつくる。
つづいてPrintingクラス

class Printing(object):
    def printWeak(self):
        pass

    def printStrong(self):
        pass

ここではprintWeakメソッドと printStrongメソッドを宣言してるだけ。
ここは元はインターフェースなのでpythonだと意味がないのだが、練習なので。
次はPrintBannerクラスのインスタンスを呼んでメソッドを実行
ここがBannerクラスを使ってPrintingクラスを満たすアダプターの役割を果たすことになる。

class PrintBanner(Banner):
    def __init__(self, word):
        super(PrintBanner, self).__init__(word)

    def printWeak(self):
        self.showWithParen()

    def printStrong(self):
        self.showWithAster()

ここではBannerクラスを継承して、Printingクラスを実装している。
super関数でBannerクラスのインスタンスを呼んで__init__(word)メソッドを使う部分は
pythonの継承では無くても大丈夫みたいだけど、練習としてそのまま使ってみた。
後はprintWeakメソッドとprintStrongメソッドを実装してやる。
最後にPrintBannerクラスのインスタンスを呼んでメソッドを実行。

p = PrintBanner("Hello")
p.printWeak()
p.printStrong()

実行結果は以下となる。

C:\works\python\book1>python adapterk.py
(Hello)
*Hello*

今度は委譲を使ったパターン(adapteri.py)。
BannerクラスとPrintingクラスに最後のPrintBannerクラスのインスタンスを呼んでメソッドを実行
する部分はそのまま。
異なるのはPrintBannerクラス。

class PrintBanner(Printing):
    def __init__(self, word):
        self.banner = Banner(word)

    def printWeak(self):
        self.banner.showWithParen()

    def printStrong(self):
        self.banner.showWithAster()

今度はPrintingクラスを継承して、まずBannerクラスのインスタンスを呼んでいる。
それで呼んだインスタンスに対してshowWithParenメソッドとshowWithAsterメソッドを
使うことによりprintWeakメソッドとprintStrongメソッドを実装している。
最終的に実行すると。

C:\works\python\book1>python adapteri.py
(Hello)
*Hello*

super関数

super()関数を使うとベースクラスのメソッドを呼べるみたい。
具体的に試してみる。
まずはOneというクラスを作ってメソッドを定義して、Oneクラスを継承するTwoというクラスを作る。

>>> class One(object):
...     def fone(self):
...         print "one"
...
>>> class Two(One):
...     pass
...

次にTwoクラスのインスタンスを作っておく。

>>> t = Two()
>>> t
<__main__.Two object at 0x00D665B0>

それでsuper関数を使って次のように書いてやると、

>>> super(Two, t).fone
<bound method Two.fone of <__main__.Two object at 0x00D665B0>>

第1引数にはクラス名、第2引数にはそのクラスインスタンスを与えてやるとbound method
が返ってきてる。そのままfoneメソッドを使ってやると,

>>> super(Two, t).fone()
one

となってfoneメソッドの実行結果が返ってくる。
super()関数がベースクラスのインスタンスを返してくれてベースクラスのメソッドが使えるわけか。

ポリモーフィズム

ポリモーフィズムって何なのかってことをつかむために「じゅんいち☆かとうの技術日誌」さんhttp://d.hatena.ne.jp/j5ik2o/20080508/1210246936
に書かれていたサンプルをpythonで書いてみた。
Javaのサンプルコードをそのままpythonに適用しただけなので、基本的に冗長になってます。
まずはAnimal class
pythonにはインターフェイスが無いのでここは実質意味は無いけど練習なのでとりあえず書くと、

>>> class Animal:
   ...:     def cry(self):
   ...:         pass
   ...:     def run(self):
   ...:         pass
   ...:     def sit(self):
   ...:         pass
   ...:     def sanpo(self):
   ...:         pass
   ...:
   ...:

ここではメソッドを宣言してるだけ。
次はAbstractAnimal class

>>> class AbstractAnimal(Animal):
   ...:     def sanpo(self):
   ...:         self.run()
   ...:         self.cry()
   ...:         self.sit()
   ...:
   ...:

sanpo()メソッドを実装。
つづいてCat class

>>> class Cat(AbstractAnimal):
   ...:     def cry(self):
   ...:         print "nyannyan"
   ...:     def run(self):
   ...:         print "nyannyan run"
   ...:     def sit(self):
   ...:         print "nyanyan sit"
   ...:
   ...:

ここでは猫を実装。
ここでちょっと試してみる。
Cat classのインスタンスオブジェクトを呼び出して、sanpo()メソッドを使うと、

>>> cat = Cat()

>>> cat.sanpo()
nyannyan run
nyannyan
nyanyan sit

大丈夫みたいなので、犬を実装してやっぱり試してみると、

>>> class Dog(AbstractAnimal):
   ...:     def cry(self):
   ...:         print "wanwan"
   ...:     def run(self):
   ...:         print "wanwan run"
   ...:     def sit(self):
   ...:         print "wanwan sit"
   ...:
   ...:

>>> dog = Dog()

>>> dog.sanpo()
wanwan run
wanwan
wanwan sit

次はAnimalFactory class
ここもインターフェイスだからあまり意味なし。

>>> class AnimalFactory(object):
   ....:     def create(self, animalword):
   ....:         pass
   ....:
   ....:

ここではcreateメソッドを宣言。
最後にAnimalFactoryImpl class

>>> class AnimalFactoryImpl(AnimalFactory):
   ....:     def create(self, animalword):
   ....:         if animalword.lower() == "dog":
   ....:             return Dog()
   ....:         elif animalword.lower() == "cat":
   ....:             return Cat()
   ....:         return None
   ....:
   ....:

ここではcreateメソッドを実装。
それではAnimalFactoryImpl classのインスタンスオブジェクトを呼び出して
createメソッドで"dog"を指定してやると、

>>> af = AnimalFactoryImpl()

>>> animal = af.create("dog")

>>> animal.sanpo()
wanwan run
wanwan
wanwan sit
変数animalにDog classのインスタンスを代入できて、sanpoメソッドを使うと。

"cat"を指定すれば、Cat classのインスタンスができる。

>>> animal2 = af.create("cat")

>>> animal2.sanpo()
nyannyan run
nyannyan
nyanyan sit

Dog classもCat classもsanpoメソッドを実装しているから共通のメソッドが使える。
つまり、メソッドを呼び出す側を共通化できることがポリモーフィズムなわけだ。

クラス-クラスを作る-

pythonの標準モジュールには多くのクラスが既に定義されているらしいが、
独自に作ることもできるらしい。
「みんなのPython」に書かれている例の通りにブックマーククラスを定義してみる。
定義にはclass文を使って、つづいてクラスの名前を添えるらしい。やってみるとブロックを記述
できるようになる。

>>> class Bookmark:
...

クラスのブロック内ではクラスのメソッドを定義できて、メソッドの定義にはdef文を使うらしい。
第一引数にはselfという引数を添える決まりらしい。
クラスの概要を表示するメソッドを定義してみると、

>>> class Bookmark:
...     def print_outline(self):
...         print "[Bookmark_class]"
...
>>>

定義したメソッドを使ってみると、

>>> b = Bookmark()
>>> b.print_outline()
[Bookmark_class]

クラスにはアトリビュート(属性)なるものを定義できるらしい。
アトリビュートはクラスが持つ変数のようなもので、これを利用するとインスタンスオブジェクトに
独自のデータを保存できるらしいが、いまいち良くわからない。
新しいアトリビュートを作るときはクラス内でメソッドを定義して、その中で代入を行えばよいらしい。
メソッドの第一引数selfに、ドット区切りで設定するアトリビュート名を続けて変数みたいに代入するらしい。
いまいちわかりにくいのでとりあえずやってみると、

>>> class Bookmark:
...     def print_outline(self):
...         print "[Bookmark_class]"
...     def set_title(self, title):
...         self.title = title
...     def get_title(self):
...         return self.title
...
>>> b = Bookmark()
>>> b.set_title("test title")
>>> b.get_title()
'test title'

set_title()メソッドの第二引数をself.titleというアトリビュートに代入しているわけだ。
それで、get_titleメソッドの戻り値にアトリビュートを設定していると。
それで、実際にset_title()メソッドを使ってタイトルを指定してやると、get_title()メソッド
でそれが返ってくるようになるわけか。
確かにクラス内の変数みたいに使えるのか。とりあえず理解できた気がする。