Python.use(better, src=”PyPy”) #003: クラス pycodegen.Expression

中級篇

Python.use(better, src=”PyPy”) # ソースコードの歩き方《中級篇》
ソースコードの歩き方《PyPy1.2》

《著》小粒ちゃん@湘南組、小粒ちゃん@博多組《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2008/11/25 ● 第2版♪2010/04/29

PyPy1.2 のリリースを機に、PyPy1.1 版を再構成したものです。
※ compiler の傘下にあるモジュールは、PyPy1.1.0 からの変更はありません。


クラス pycodegen.Expression


この先で迷子にならないように、謎を解く鍵を確認しておきます。

$ cat compiler/pycodegen.py 
...
def compile(source, filename, mode, flags=None, dont_inherit=None):
    ...
        gen = Expression(source, filename)
    ...
    gen.compile()
    #                この行間を読み解くのが秘訣 (@.@)
    return gen.code

メソッド呼び出し compile() をリターン値にはせずに、属性 .code を参照しているので、メソッド呼び出しの「副作用」が謎を解く鍵になります。そこで、メソッド compile の本体に歩を進めると、

$ cat compiler/pycodegen.py 
...
class Expression(AbstractCompileMode):

    mode = "eval"

    def compile(self):
        tree = self._get_tree()
        gen = ExpressionCodeGenerator(tree)
        self.code = gen.getCode()

確かに、属性 .code を再設定しているのが分かります。

《TIPS》コードの行間を読む:副作用を前提にしたコードは読み辛く、バグの温床になりがちです。その一方で、副作用を暗示した「阿吽の呼吸」を読み解く術も必要です。「アマ」グラマーには諸手を挙げてお勧めできませんが、「プロ」グラマーには「匠」を凝らす術が求められる場面も少なくありません。コードの行間を読めるようになると、ひと味違うプログラミングの「醍醐味」を堪能できます。□

■ 新たな謎の組織(ExpressionCodeGenerator)と出生の秘密

しかし、これですべての謎が解明された訳ではありません。ようやく追いつめた実行犯の背後には、謎の組織 ExpressionCodeGenerator の存在が…。よくある連続ドラマの展開にも似ています。ここでは、副作用をもたらす源泉が、新たな登場人物 gen の背後 getCode() に隠されているのが分かります。そして、物語は新たな展開へと続きます。


ところが、その謎解きには新たな鍵 tree が必要です。しかも、その鍵を握っているのは、自分 self が属する組織(クラス)だと知ります。メソッド _get_tree は、どこに隠されているのでしょう。

$ cat compiler/pycodegen.py 
...
class AbstractCompileMode:

    mode = None # defined by subclass
    ...
    def _get_tree(self):
        #        謎を解く鍵はここに ¬(@.@)

    def compile(self):
        pass # implemented by subclass

    def getCode(self):
        return self.code

実は、その鍵は自身のルーツ(先祖)にありました。つまり、親クラス AbstractCompileMode から継承した資産だったのです。

《TIPS》抽象メソッドの意味(意義):モジュール pycodegen には、次のように

class Expression(AbstractCompileMode):
class Interactive(AbstractCompileMode):
class Module(AbstractCompileMode):

AbstractCompileMode の直系がいくつか存在します。

AbstractCompileMode
- Expression
- Interactive
- Module

すると、AbstractCompileMode の傘下にある子孫クラス(のインスタンス)はどれも、同じメソッド呼び出し _get_tree() に呼応して、異なる動作を示すものと期待されます。そのため、メソッド _get_tree の本体には、特定の子孫クラスに依存しない抽象表現だけを記述します。□


TOP
》作業中です《


関連記事

Last updated♪2010/05/17