Python.use(better)《3》継承に警鐘を鳴らす(その参)

記事一覧 Python.use(better)《Python3.1》

継承に警鐘を鳴らす(その参)

《著》後藤いるか・伊藤うさぎ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
第1版♪1988/05/23 ● 第2版♪2001/01/29 ● 第3版♪2009/12/15

オブジェクト指向プログラミング〔OOP〕の基本概念の理解を深めます。
※ JPython1.1/Jython2.2 で作成した例題を、Python3.1 で再構成しました。


継承に警鐘を鳴らす(その参)

継承の概念を実現するのに、いくつかの方法があります。そのひとつが、クラスを利用するというものです。まず、クラスをどのように表現するかを紹介します。


《note》図は、簡略した辞書のモデルを含みます。詳細は、以下(および関連記事)で紹介します。□

■ クラスを定義する

単独でクラスを定義します。

    class Piyo:
        def happy(self):
            print("Are you Happy?")

クラス Piyo には、メソッド happy を定義します。

■ クラスオブジェクト

クラスも「呼び出し可能オブジェクト」なので、演算子 () を利用できます。

>>> p1 = Piyo(); p1
<__main__.Piyo object at 0x135b910>

クラスオブジェクト Piyo に演算子 () を適用すると、新たなインスタンスオブジェクトを生成します。変数 p1 は、生成した(クラス Piyo の)インスタンスオブジェクトを束縛します。対話モードでは、式 p1 を評価すると、変数 p1 が束縛するオブジェクトに固有の識別情報が出力されます。すると、p1 は、Piyo のインスタンスオブジェクト __main__.Piyo object で、固有の識別情報 0x135b910 を持つのが分かります。この識別情報は、その状況(実行環境)ごとに値が異なります。

    
Are you Happy?
式 p1.happy() を評価すると、インスタンスオブジェクト p1 が属するクラス Piyo で定義したメソッド happy を呼び出します。すると、メソッド happy の本体に記述したコードの断片を評価して、文字列 "Are you Happy?" を出力します。
■ 特殊属性:__class__
特殊属性 __class__ を参照すると、そのインスタンスオブジェクトが属する、クラスオブジェクトが得られます。
>>> hex(id(p1.__class__))
'0x4b2a40'
>>> hex(id(Piyo))
'0x4b2a40'
p1 のインスタンス属性 __class__ を介して、クラスオブジェクト Piyo が得られます。つまり、クラスと同じ名前の変数 Piyo が束縛するオブジェクトと見なせます。
■ 特殊属性:__dict__
特殊属性 __dict__ を参照すると、メソッド辞書オブジェクトが得られます。
>>> hex(id(p1.__class__.__dict__))
'0x135b9d0'
>>> hex(id(Piyo.__dict__))
'0x135b9d0'
p1 のインスタンス属性 __class__ を介しても、Piyo のクラス属性 __dict__ を介して得られるのは、同じメソッド辞書オブジェクトです。
>>> hex(id(p1.__class__.__dict__["happy"]))
'0x125e0c0'
メソッド辞書オブジェクトは、メソッドと同じ名前のキー属性を持ちます。そのため、キー属性 "happy" を参照すると(対応する値属性として)関数オブジェクト happy が得られます。
■ 関数オブジェクト
関数も「オブジェクト」なので、固有の識別情報を持ちます。
>>> Piyo.happy

>>> Piyo.__dict__["happy"]

クラスオブジェクトも(他のオブジェクトと同様に)属性を介して、他のオブジェクトを参照できます。ただし、クラスオブジェクト Piyo が、クラス属性 happy を持つかのように見えて、クラス属性 __dict__ を介して、メソッド辞書からクラス属性と同じ名前の文字列(キー要素)対応する関数オブジェクト(値要素)を得ています。
■ 特殊属性:__func__
特殊属性 __func__ を参照すると、そのメソッドオブジェクトが保持する、関数オブジェクトが得られます。
>>> p1.happy
>
>>> hex(id(p1.happy))
'0x124e620'
>>> hex(id(p1.happy.__func__))
'0x125e0c0'
インスタンスオブジェクトも(他のオブジェクトと同様に)属性を介して、他のオブジェクトを参照できます。ただし、インスタンスオブジェクト p1 が、インスタンス属性 happy を持つものの、特殊属性 __func__ を介さないと、関数オブジェクトは得られません。そのため、p1.happy という表現は、p1.__class__.__dict__["happy"] の簡略表記(近道)と見なせます。
■ 束縛メソッド
メソッド呼び出しには、実行時に確定するオブジェクト(慣例では、変数 self で参照する)の存在が不可欠です。そのため「束縛メソッド」と「非束縛メソッド」とに分類されます。
>>> p1 = Piyo()
>>> p1.happy()        #1: bound method
Are you Happy?
>>> Piyo.happy(p1)    #2: un-bound method
Are you Happy?
>>> Piyo.__dict__["happy"](p1)
Are you Happy?
束縛メソッド happy #1 は、実行時に確定するインスタンスオブジェクト p1 の他に、実引数を指定する必要はありません。しかし、未束縛メソッド happy #2 は、1つの実引数(インスタンスオブジェクト p1)を指定する必要があります。 》こちらに移動中です《TOP

関連記事

Last updated♪2010/01/12