Hatena::ブログ(Diary)

tachikawa844の日記

2009-02-16

ファイルからのデータ入力

| 15:52

MySQLを始めて勉強中。データベースとテーブルを作成した後、既存のcsvファイルをテーブルに流し込む操作をやってみた。

最初にテキストの例のとおりに以下のコマンドでやったみた。

mysql> load data infile "指定ファイルの絶対パス" into table テーブル名 fields terminated by "," lines terminated by "\n";

するとこんなエラーになった。

ERROR 13 (HY000): Can't get stat of '指定ファイルの絶対パス' (Errcode: 2)

そこで調べてみると、ここに(http://mlog.euqset.org/archives/ml@mysql.gr.jp/14306.html)解決策が出ていた。

なんでもload data infileはMySQLサーバ側にファイルを読み込ませる文らしい。

mysqlユーザではサーバマシンの指定したファイルにアクセスできないのでエラーになるみたい。

一方、LOAD DATA LOCAL INFILEという文だとMySQLクライアント側にファイルを読み込ませることができるらしいので

早速試してみるとうまくいった。

mysql> load data local infile "指定ファイルの絶対パス" into table テーブル名 fields terminated by "," lines terminated by "\n";
Query OK, 3 rows affected (0.00 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

はいちゃんちゃんちゃん!!!!はいちゃんちゃんちゃん!!!! 2009/08/16 20:07
もーさすがに3回は果てるってーー!!!(>_<)
連続じゃないだけマシだけど1 0 万の為とはいえ3回ヤるとティ ンコさんが火を噴きそうなくらい真っ赤っ赤だよ(^^;
まー何気に足 コ キしてもらったのって初めてだし、得っちゃ得だけどねーwww

http://kachi.strowcrue.net/neYEjnT/

2009-01-12

Bridgeパターン

| 18:58

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターンを書いてみる。

今回の題材はBridgeパターン。このパターンは機能のクラス階層と実装のクラス階層を結びつけるというものらしい。

まずは機能のクラス階層と実装のクラス階層とは何なのかってことから勉強。

あるクラスclsがあって、clsに新しい機能を追加する(新しいメソッドの追加)ときにはclsのサブクラスとしてcls2をつくる。

これで一段階のクラス階層ができる。さらにcls2に新しい機能を追加するならcls2のサブクラスcls3をつくる。これで二段階の

クラス階層ができて、この階層は機能の追加のためにつくられた階層となる。これを機能のクラス階層とすると。

これに対して、あるクラスclsではメソッドの宣言だけを行い、そのメソッドの実装をclsのサブクラスcls2で行った場合、clsとcls2に

よってできるクラス階層を実装のクラス階層とする。

クラス階層が1つだと機能のクラス階層と実装のクラス階層が混ざってしまい、クラス階層が複雑になりプログラムの見通しが悪く

なる危険がある。そこで、機能のクラス階層と実装のクラス階層を2つの独立したクラス階層に分けることが大事みたい。しかし、分けただけではダメで2つのクラス階層をつなぐことが必要。Bridgeパターンはそのつなぐ役割を果たす。

サンプルプログラムbridge.py) は何かを表示するというもの。具体的には以下のよう。

まずDisplayクラス

import random
import sys

class Display(object):
    def __init__(self, impl):
        self.impl = impl
    def opening(self):
        self.impl.rawOpening()
    def printing(self):
        self.impl.rawPrinting()
    def closing(self):
        self.impl.rawClosing()
    def display(self):
        self.opening()
        self.printing()
        self.closing()

このクラスは機能のクラス階層の最上位のクラス。コンストラクタのimplは実装を表すクラスのインスタンスが渡される。

このインスタンスが2つのクラス階層をつなぐ。

次はCountDisplayクラス

class CountDisplay(Display):
    def __init__(self, impl):
        super(CountDisplay, self).__init__(impl)
    def multiDisplay(self, times):
        self.opening()
        for i in range(times):
            self.printing()
        self.closing()

このクラスはDisplayクラスに指定回数表示するという機能(multiDisplayメソッド)を追加したもの。

よってこれは機能のクラス階層。

次はDisplayImplクラス

class DisplayImpl(object):
    def rawOpening(self):
        pass
    def rawPrinting(self):
        pass
    def rawClosing(self):
        pass

このクラスは実装のクラス階層の最上位のクラス。Displayクラスのopening,printing,closingメソッドに対応するメソッドの

宣言のみ。

次はStringDisplayImplクラス

class StringDisplayImpl(DisplayImpl):
    def __init__(self, st):
        self.st = st
        self.width = len(st)
    def rawOpening(self):
        self.printLine()
    def rawPrinting(self):
        print "|%s|" %self.st
    def rawClosing(self):
        self.printLine()
    def printLine(self):
        print "+%s+" %("-"*self.width)

このクラスはDisplayImplクラスのサブクラスとしてメソッドを実装。ここは実装のクラス階層。

ここにさらにクラスを追加して、ランダム回数表示する処理を実現するにはどうするか?

機能のクラス階層に追加すれば良いのではってことでRandomDisplayクラス

class RandomDisplay(CountDisplay):
    def random_Display(self, times):
        self.multiDisplay(random.randrange(times))

さらにクラスを追加して、テキストファイルの内容を表示する処理を実現するにはどうするか?

実装のクラス階層に追加すれば良いのではってことでTextDisplayImplクラス

class TextDisplayImpl(DisplayImpl):
    def __init__(self, textfile):
        self.textfile = textfile
    def rawOpening(self):
        self.f = open(self.textfile)
    def rawPrinting(self):
        print self.f.readlines()[0]
    def rawClosing(self):
        self.f.close()

さらにクラスを追加して、

<>
<*>
<**>
<***>

とか、

|-
|##-
|####-
|######-
|########-
|##########-

みたいな模様を表示するにはどうするか?

今度は機能と実装の両階層に追加すれば良いのではってことでIncreasingDisplayクラスとDecoDisplayImplクラス

class IncreasingDisplay(CountDisplay):
    def __init__(self, impl, increase):
        super(IncreasingDisplay, self).__init__(impl)
	self.increase = increase
    def increasing_Display(self, max_number):
        self.max_number = max_number
	for i in range(0, max_number, self.increase):
	    self.multiDisplay(i)

class DecoDisplayImpl(DisplayImpl):
    def __init__(self, start, deco, last):
        self.start = start
        self.deco = deco
        self.last = last
    def rawOpening(self):
        sys.stdout.write(self.start)
    def rawPrinting(self):
        sys.stdout.write(self.deco)
    def rawClosing(self):
        sys.stdout.write("%s\n" %(self.last))

最後に動作テスト部分

if __name__=="__main__":
    d1 = Display(StringDisplayImpl("Hello, Japan."))
    d2 = CountDisplay(StringDisplayImpl("Hello, World."))
    d3 = CountDisplay(StringDisplayImpl("Hello, Universe."))
    d4 = RandomDisplay(StringDisplayImpl("Hello, Random."))
    d5 = Display(TextDisplayImpl("newfile.txt"))
    d6 = IncreasingDisplay(DecoDisplayImpl("<", "*", ">"), 1)
    d7 = IncreasingDisplay(DecoDisplayImpl("|", "#", "-"), 2)
    d1.display()
    d2.display()
    d3.display()
    d3.multiDisplay(5)
    d4.random_Display(5)
    d5.display()
    d6.increasing_Display(4)
    d7.increasing_Display(12)

実行結果は以下。

C:\works\python\book1>python bridge
+-------------+
|Hello, Japan.|
+-------------+
+-------------+
|Hello, World.|
+-------------+
+----------------+
|Hello, Universe.|
+----------------+
+----------------+
|Hello, Universe.|
|Hello, Universe.|
|Hello, Universe.|
|Hello, Universe.|
|Hello, Universe.|
+----------------+
+--------------+
|Hello, Random.|
|Hello, Random.|
|Hello, Random.|
+--------------+
test! test! test!
<>
<*>
<**>
<***>
|-
|##-
|####-
|######-
|########-
|##########-

2009-01-10

Abstract Factoryパターン

| 13:18

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターンを書いてみる。

今回の題材はAbstract Factoryパターン。名前の通り抽象的な工場で、抽象的な部品を組み合わせて抽象的な製品を作るらしい。

わかりにくいが、要は部品の具体的な実装は気にせずに部品を組み立てて製品としてまとめてしまうというものみたい。

具体的な実装はサブクラスで行う。

サンプルのプログラムは階層構造を持ったリンク集HTMLファイルとして作るもの。

はじめに抽象的な工場、部品、製品を含む部分(factory.py)。

# -*- coding: utf-8 -*-
class Item(object):
    def __init__(self, caption):
        self.caption = caption
    def makeHTML(self):
        pass

class Link(Item):
    def __init__(self, caption, url):
        super(Link, self).__init__(caption)
        self.url = url

class Tray(Item):
    def __init__(self, caption):
        super(Tray, self).__init__(caption)
        self.tray = []
    def add(self, item):
        self.tray.append(item)

class Page(object):
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.content = []
    def add(self, item):
        self.content.append(item)
    def output(self):
        self.filename = "%s.html" %self.title
        writer = open(self.filename, "w")
        writer.write(self.makeHTML())
        writer.close()
        print "%sを作成しました。" %self.filename
    def makeHTML(self):
        pass

class Factory(object):
    @classmethod
    def getFactory(cls, classname):
        module, kls = classname.rsplit(".", 1)
        return getattr(__import__(module), kls)()
    def createLink(self, caption, url):
        pass
    def createTray(self, caption):
        pass
    def createPage(self, title, author):
        pass

ItemクラスはLinkクラスとTrayクラスを統一的に扱うために両者のスーパークラスになる。

LinkクラスはHTMLのリンクを抽象的に表現したクラス。Trayクラスはaddメソッドを使って複数の項目をひとまとめにする。

PageクラスはHTMLページ全体を抽象的に表現したクラス。addメソッドで項目を追加、outoutメソッドで自分自身の内容を

ファイルに書き込む。

Factoryクラスは抽象的な工場。getFactoryメソッドはクラス名を指定して工場のインスタンスをつくる。

getattr()関数は指定したオブジェクトの属性を返してくる。ここではclassnameで指定されたクラスのモジュールインポート

して、モジュール内のクラスのインスタンスが返り、そのインスタンスを新しくつくってgetFactoryメソッドの戻り値にしている。

次に動作テスト用の実行部分(abstract_factory_main.py)。

# -*- coding: utf-8 -*-
from factory import *
import sys
factory = Factory.getFactory(sys.argv[1])

asahi = factory.createLink("朝日新聞", "http://www.asahi.com/")
yomiuri = factory.createLink("読売新聞", "http://www.yomiuri.co.jp/")
us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/")
jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/")
excite = factory.createLink("Exite", "http://www.excite.com/")
google = factory.createLink("Google", "http://www.google.com/")

traynews = factory.createTray("新聞")
traynews.add(asahi)
traynews.add(yomiuri)

trayyahoo = factory.createTray("Yahoo!")
trayyahoo.add(us_yahoo)
trayyahoo.add(jp_yahoo)

traysearch = factory.createTray("サーチエンジン")
traysearch.add(trayyahoo)
traysearch.add(excite)
traysearch.add(google)

page = factory.createPage("LinkPage", "name")
page.add(traynews)
page.add(traysearch)
page.output()

抽象的な工場で抽象的な部品をつくり、抽象的な製品を組み立てる。具体的な工場のクラス名はコマンドライン引数

指定する。この引数からgetFactoryで工場をつくって変数factoryに代入する。後はLink,Trayをつくってひとまとめにして

から、Pageをつくってoutput。

ここからは具体的な工場、部品、製品を含む部分(listfactory.py)。

import factory
class ListFactory(factory.Factory):
    def createLink(self, caption, url):
        return ListLink(caption, url)
    def createTray(self, caption):
        return ListTray(caption)
    def createPage(self, title, author):
        return ListPage(title, author)

class ListLink(factory.Link):
    def __init__(self, caption, url):
        super(ListLink, self).__init__(caption, url)
    def makeHTML(self):
        return ' <li><a href="%s">%s</a></li>\n' %(self.url, self.caption)

class ListTray(factory.Tray):
    def __init__(self, caption):
        super(ListTray, self).__init__(caption)
    def makeHTML(self):
        self.buffer = []
        self.buffer.append("<li>\n")
        self.buffer.append("%s\n" %self.caption)
        self.buffer.append("<ul>\n")
        for item in self.tray:
            self.buffer.append(item.makeHTML())
        self.buffer.append("</ul>\n")
        self.buffer.append("</li>\n")
        return "\n".join(self.buffer)

class ListPage(factory.Page):
    def __init__(self, title, author):
        super(ListPage, self).__init__(title, author)
    def makeHTML(self):
        self.buffer = []
        self.buffer.append("<html><head><title>%s</title></head>\n" %self.title)
        self.buffer.append("<body>\n")
        self.buffer.append("<h1>%s</h1>\n" %self.title)
        self.buffer.append("<ul>\n")
        for item in self.content:
            self.buffer.append(item.makeHTML())
        self.buffer.append("</ul>\n")
        self.buffer.append("<hr><address>%s</address>" %self.author)
        self.buffer.append("</body></html>\n")
        return "\n".join(self.buffer)

ListFactoryクラスはFactoryクラスのcreateLink,createTray,createPageを実装。単にListLink,ListTray,ListPageのインスタンス

を返すだけ。

ListLinkクラスはmakeHTMLメソッドを実装してHTMLの断片をつくる。ListTrayクラスもmakeHTMLメソッドを実装。HTMLの断片をリストに

集めて最後につなげる。ListPageクラスでもmakeHTMLメソッドを実装してページの構成をつくる。

最後に別の具体的な工場を含む部分(tablefactory.py)。

import factory
class TableFactory(factory.Factory):
    def createLink(self, caption, url):
        return TableLink(caption, url)
    def createTray(self, caption):
        return TableTray(caption)
    def createPage(self, title, author):
        return TablePage(title, author)

class TableLink(factory.Link):
    def __init__(self, caption, url):
        super(TableLink, self).__init__(caption, url)
    def makeHTML(self):
        return '<td><a href="%s">%s</a></td>\n' %(self.url, self.caption)

class TableTray(factory.Tray):
    def __init__(self, caption):
        super(TableTray, self).__init__(caption)
    def makeHTML(self):
        self.buffer = []
        self.buffer.append("<td>")
        self.buffer.append('<table width="100%" border="1"><tr>')
        self.buffer.append('<td bgcolor="#cccccc" align="center" colspan="%s"><b>%s</b></td>' %(len(self.tray), self.caption))
        self.buffer.append("</tr>\n")
        self.buffer.append("<tr>\n")
        for item in self.tray:
            self.buffer.append(item.makeHTML())
        self.buffer.append("</tr></table>")
        self.buffer.append("</td>")
        return "\n".join(self.buffer)

class TablePage(factory.Page):
    def __init__(self, title, author):
        super(TablePage, self).__init__(title, author)
    def makeHTML(self):
        self.buffer = []
        self.buffer.append("<html><head><title>%s</title></head>\n" %self.title)
        self.buffer.append("<body>\n")
        self.buffer.append("<h1>%s</h1>\n" %self.title)
        self.buffer.append('<table width="80%" boder="3">\n')
        for item in self.content:
            self.buffer.append("<tr>%s</tr>" %item.makeHTML())
        self.buffer.append("</table>\n")
        self.buffer.append("<hr><address>%s</address>" %self.author)
        self.buffer.append("</body></html>\n")
        return "\n".join(self.buffer)

実際に実行するときは、

C:\works\python\book1>python abstract_factory_main.py listfactory.ListFactory
LinkPage.htmlを作成しました。

とすると、箇条書きを元にしたデザインのHTMLファイルがつくられる。

C:\works\python\book1>python abstract_factory_main.py tablefactory.TableFactory
LinkPage.htmlを作成しました。

とすると、表組みを元にしたデザインになる。

2009-01-06

Builderパターン

| 15:16

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターンを書いてみる。

今回の題材はBuilderパターン。複雑な構造のものを一気に組み立てるのは難しいので、事前に全体を構成する各部分をつくって

段階を踏んで構造を持ったインスタンスを組み上げていくもの。

サンプルになっているのはこのパターンを使って文書を作成するプログラムbuilder.py)。

Builderクラスで文書作成用のメソッドを決めて、Directorクラスでそのメソッドを使って文書をつくる。

どんな文書にするかはBuilderクラスのサブクラスで決まるというもの。

まずBuilderクラス

# -*- coding: utf-8 -*-
class Builder(object):
    def makeTitle(self, title):
        pass
    def makeString(self, st):
        pass
    def makeItems(self, items):
        pass
    def closing(self):
        pass

ここではメソッドの宣言だけ。

次はDirectorクラス

class Director(object):
    def __init__(self, builder):
        self.builder = builder
    def construct(self):
        self.builder.makeTitle("Greeting")
        self.builder.makeString("朝から昼にかけて")
        self.builder.makeItems(["おはようございます。", "こんにちは。"])
        self.builder.makeString("夜に")
        self.builder.makeItems(["こんばんは。", "おやすみなさい。", "さようなら。"])
        self.builder.closing()

ここでBuilderクラスで宣言したメソッドを使って文書をつくる。コンストラクタに渡されることになるのは

Builderクラスのサブクラスインスタンス。渡されるインスタンスによってどんな文書になるか変わる。

次はTextBuilderクラス

class TextBuilder(Builder):
    _buffer = []
    def makeTitle(self, title):
        self._buffer.append("===================================\n")
        self._buffer.append("[%s]" %title)
        self._buffer.append("\n")
    def makeString(self, st):
        self._buffer.append("*%s\n" %st)
        self._buffer.append("\n")
    def makeItems(self, items):
        for i in items:
           self._buffer.append(" +%s\n" %i)
        self._buffer.append("\n")
    def closing(self):
        self._buffer.append("===================================\n")
    def getResult(self):
        return "\n".join(self._buffer)

ここはBuilderクラスのサブクラスでプレーンテキストで文書をつくる。リストに文書の各部を順に入れていき、joinメソッドで

つなげた結果が文字列で返ってくる。

次はHTMLBuilderクラス

class HTMLBuilder(Builder):
    _buffer = []
    def makeTitle(self, title):
        self.title = title
        self.filename = "%s.html" %title
        self._buffer.append("<html><head><title>%s</title></head><body>\n" %title)
        self._buffer.append("<h1>%s</h1>\n" %title)
    def makeString(self, st):
        self.st = st
        self._buffer.append("<p>%s</p>\n" %st)
    def makeItems(self, items):
        self.items = items
        self._buffer.append("<ul>\n")
        for i in items:
            self._buffer.append("<li>%s</li>\n" %i)
        self._buffer.append("</ul>\n")
    def closing(self):
        self._buffer.append("</body></html>\n")
    def getResult(self):
        self.writer = open(self.filename, "w")
        self.writer.write("\n".join(self._buffer))
        self.writer.close()
        return self.filename

ここもBuilderクラスのサブクラスHTMLファイルとして文書をつくる。ここでもリストに文書の各部を入れていってつなげたものを

ファイルに書き込む。結果はファイル名として返ってくる。

最後に動作テスト用の部分

if __name__=="__main__":
    import sys
    if len(sys.argv) == 1 or len(sys.argv) >= 3:
        print "python builder.py plain => plain text"
        print "python builder.py html => HTML text"
    elif sys.argv[1] == "plain":
        textbuilder = TextBuilder()
        director = Director(textbuilder)
        director.construct()
        result = textbuilder.getResult()
        print result
    elif sys.argv[1] == "html":
        htmlbuilder = HTMLBuilder()
        director = Director(htmlbuilder)
        director.construct()
        filename = htmlbuilder.getResult()
        print "%sが作成されました。" %filename
    else:
        print "python builder.py plain => plain text"
        print "python builder.py html => HTML text"

コマンドラインで指定した形式によってつくられる文書が変わる。

plainを指定するとTextBuilderクラスのインスタンスがDirectorクラスのコンストラクタに渡るし、htmlを指定すれば

HTMLBuilderクラスのインスタンスがDirectorクラスのコンストラクタに渡る。

実行結果は以下。

C:\works\python\book1>python builder.py plain
===================================

[Greeting]


*朝から昼にかけて



 +おはようございます。

 +こんにちは。



*夜に



 +こんばんは。

 +おやすみなさい。

 +さようなら。



===================================
C:\works\python\book1>python builder.py html
Greeting.htmlが作成されました。

2009-01-02

Prototypeパターン

| 18:16

結城浩さんの「Java言語で学ぶデザインパターン入門」を題材にpythonデザインパターンを書いてみる。

今回の題材はPrototypeパターン。クラスからインスタンスをつくるのではなく、インスタンスをコピーすることで、

インスタンスから別のインスタンスをつくるというもの。

pythonでは copyモジュールの deepcopy関数を使うことでインスタンスのコピーをすることができるようなので、

まずは copyモジュールについて学習。copyモジュールは浅いコピーと深いコピー操作を提供してくれるらしい。

浅い (shallow) コピーと深い (deep) コピーの違いが関係してくるのは、複合オブジェクト (リストやクラスインスタンス

ような他のオブジェクトを含むオブジェクト) だけということらしい。

浅いコピー (shallow copy) は新たな複合オブジェクトを作成し、その後 (可能な限り) 元のオブジェクト中に見つかったオブジェクトに対する 参照 を挿入するらしい。

深いコピー (deep copy) は新たな複合オブジェクトを作成し、その後元のオブジェクト中に見つかったオブジェクトの コピー を挿入するらしい。

とりあえず実験。まずは単純にコピー。

>>> import copy
>>> ori = "Hello!"
>>> c1 = copy.copy(ori)
>>> c2 = copy.deepcopy(ori)
>>> c1
'Hello!'
>>> c2
'Hello!'

次にリストのコピー。

>>> lis = [1,2,3]
>>> lis1 = copy.copy(lis)
>>> lis2 = copy.deepcopy(lis)
>>> lis
[1, 2, 3]
>>> lis1
[1, 2, 3]
>>> lis2
[1, 2, 3]
>>> lis[0] = "Hello!"
>>> lis
['Hello!', 2, 3]
>>> lis1
[1, 2, 3]
>>> lis2
[1, 2, 3]

次はリストのリストのコピー。

>>> lis3 = [[1,2,3]]
>>> lis4 = copy.copy(lis3)
>>> lis5 = copy.deepcopy(lis3)
>>> lis3
[[1, 2, 3]]
>>> lis4
[[1, 2, 3]]
>>> lis5
[[1, 2, 3]]
>>> lis3[0][0] = "Hello!"
>>> lis3
[['Hello!', 2, 3]]
>>> lis4
[['Hello!', 2, 3]]
>>> lis5
[[1, 2, 3]]

lis3に対する参照を行った後では浅いコピー(lis4)と深いコピー(lis5)の内容に違いが出た。

これが浅いコピーでは元のオブジェクト中に見つかったオブジェクトに対する 参照 を挿入して、

深いコピーでは元のオブジェクト中に見つかったオブジェクトの コピー を挿入するってことなのか。

要は深いコピーではオブジェクトの内部を辿って複製してくれるというわけか。

浅いコピーで複製されたオブジェクトは、可能な限り参照として渡されちゃうのでリストや辞書などの場合

その要素に参照があればそれは参照として渡されるってことでいいのかな。なのでクラスインスタンスのコピーでも

インスタンスの実体を複製するには深いコピーを行わなきゃならないってことかな。

ではデザインパターンの実装へ。サンプルプログラムは、文字列を枠線で囲って表示したり、下線を付けて表示したり

するもの(prototype.py)。

はじめにProductクラス。

import copy

class Product(object):
    def use(self, s):
        pass
    def createClone(self):
        pass

ここは元々インターフェースなのでメソッドの宣言のみ。

次にManageクラス。

class Manager(object):
    __showcase = dict()
    def register(self, name, proto):
        self.__showcase[name] = proto
    def create(self, protoname):
        p = self.__showcase.get(protoname)
        return p.createClone()

ここではregisterメソッドで製品の名前とProductクラスのインスタンスの一組を辞書に登録。

createメソッドはcreateCloneメソッドを使ってインスタンスを複製する。

次にMessageBoxクラス。

class MessageBox(Product):
    def __init__(self, decochar):
        self.decochar = decochar
	
    def use(self, s):
        length = len(s)
	deco = self.decochar * (length + 4 )
	print deco
	print self.decochar,s,self.decochar
	print deco
	
    def createClone(self):
        p = copy.deepcopy(self)
	return p

ここはProductクラスの実装を行っている。useメソッドは与えられた文字列をdecocharで囲むというもの。

createCloneメソッドはdeepcopy関数を使って自分自身のインスタンスを複製する。

次にUnderlinePenクラス。

class UnderlinePen(Product):
    def __init__(self, ulchar):
        self.ulchar = ulchar
	
    def use(self, s):
        length = len(s)
	print '"%s"' %s
	print " %s " %(self.ulchar * length)
	
    def createClone(self):
        p = copy.deepcopy(self)
	return p

ここもProductクラスの実装。ulcharで与えられる下線を付ける。

最後に動作テスト用のクラス。

if __name__== "__main__":
    manager = Manager()
    upen = UnderlinePen("~")
    mbox = MessageBox("*")
    sbox = MessageBox("/")
    manager.register("strong message", upen)
    manager.register("warning box", mbox)
    manager.register("slash box", sbox)
    
    p1 = manager.create("strong message")
    p1.use("Hello, world.")
    p2 = manager.create("warning box")
    p2.use("Hello, world.")
    p3 = manager.create("slash box")
    p3.use("Hello, world.")

最初にManagerクラスのインスタンスを作る。そのインスタンスに対してUnderlinePenクラスのインスタンス

MessageBoxクラスのインスタンスを登録しておく。

実行結果は、

C:\works\python\book1>python prototype.py
"Hello, world."
 ~~~~~~~~~~~~~
*****************
* Hello, world. *
*****************
/////////////////
/ Hello, world. /
/////////////////
Connection: close