Python 弾丸ツアー #DP: ツリー ... step 4: アプリケーションを起動する

OOPデザインパターンリファクタリング

Python.use(better); Python 弾丸ツアー #DP: Tkinter/Python
>>> ツリー(階層構造)
step 4: アプリケーションを起動する
《Python3.1|Jython2.5|IronPython2.6》

《著》小粒ちゃん@湘南組《監修》小泉ひよ子とタマゴ倶楽部
第0版♪2001/03/02 ● 第1版♪2003/05/23 ● 第4版♪2010/03/08

step 4: コードの解説

■ アプリケーションを起動する
from tkinter import *

## ----------------------------------------
def tips():
    root = Tk()
    root.title("Step4: Visitor")
    root.geometry("180x50")

    path = "Python-3.0/Mac/BuildScript"
    tips = TIPS(root, path)
    tips.createNodes()
    tree = TextTreeWidget  (tree=tips.tree)
    tree = ButtonTreeWidget(tree=tips.tree)
    print("-"*40,"print(tips.tree)")
    print(tips.tree)
    print("-"*40,"tips.tree.print()")
    tips.tree.print()

    root.mainloop()

 ̄アプリケーションを起動すると、フォルダー path を頂点とするツリー(フォルダー/ファイルの階層構造)を表示します。step3 と違って、GUI コンポーネントを多用した ButtonTreeWidget とは別に、文字列を表示するだけのコンポーネントを利用した TextTreeWidget が現れます。

■ Composite::Component
from os import listdir
from os.path import join, isdir
from functools import reduce
from os.path import getsize, getatime, getmtime, getctime
from time import ctime

## ---------------------------------------- Composite::Component
class Component(object):
    def __init__(self, path, item):
        self.path = path
        self.item = item

    ## ---------------------------------------- Iterator::Iterator
    def __iter__(self): pass
    def add_(self, component): pass

    def print(self):
        for i, e in zip(self.indents(), self.items()):
            print("%s%s"%("+  "*i, e))

 ̄ここまでは、前 step3 と同じです。

■ Command::Receiver
    ## ---------------------------------------- Command::Receiver
    def createPanel(self):
        top = Toplevel()
        top.title(self.item)
        top.config(padx=16, pady=4)

        current = join(self.path, self.item)

        frame = Frame(master=top)
        frame.pack()
        item = "getsize"
        w = Label(master=frame, text=item)
        w.pack(side=LEFT)
        w = Entry(master=frame, width=10)
        w.pack(side=LEFT)
        w.insert(END, getsize(current))

        frame = Frame(master=top)
        frame.pack()
        items = "getatime", "getmtime", "getctime", 
        for i, e in enumerate(items):
            w = Label(master=frame, text=e)
            w.grid(row=i, column=0, sticky=E)
            w = Entry(master=frame, width=22)
            w.grid(row=i, column=1, sticky=W)
            w.insert(END, eval("ctime(%s('%s'))"%(e, current)))

 ̄ここまでは、前 step3 と同じです。

■ Visitor::Element
    ## ---------------------------------------- Visitor::Element
    def accept_(self, visitor, arg=0):
        eval("visitor.visit%s_(self, arg)"%self.__class__.__name__)

 ̄抽象メソッド accept_ は、共通するプロトコルを規定するもので、対象になるメソッド呼び出しが実行時に確定します。インスタンスオブジェクトが属するクラスの名前 self.__class__.__name__ が、メソッドの名前の一部に組み込まれます。

《Point》どのメソッド呼び出しが適切かは、オブジェクトごとに異なります。そこで「実行時に問題解決を図る」仕掛けがあると便利です。組み込み関数 eval を利用すると、

        eval("visitor.visit%s_(self, arg)"%self.__class__.__name__)

このとき、それが末端にあるノードなら、そのクラスの名前は "Leaf" になるので、

        eval("visitor.visit%s_(self, arg)"%"Leaf")
        eval("visitor.visitLeaf_(self, arg)")
              visitor.visitLeaf_(self, arg)

という段階を経て、メソッド呼び出し visitLeaf_() に帰着します。□

TOP
》作業中です《