Python.use(better)《5》継承に警鐘を鳴らす(その伍)
‖記事一覧‖ Python.use(better)《Python3.1》
継承に警鐘を鳴らす(その伍)
オブジェクト指向プログラミング〔OOP〕の基本概念の理解を深めます。
※ JPython1.1/Jython2.2 で作成した例題を、Python3.1 で再構成しました。
継承に警鐘を鳴らす(その伍)
継承の概念を実現するのに、いくつかの方法があります。そのひとつが、クラスを使って実現するというものです。次に(2a)親子関係にあるクラスをどのように表現するかを紹介します。
《note》図は、簡略したタプルのモデルを含みます。詳細は、以下(および関連記事)で紹介します。□
- 2006-02-05 Python.use(better) #OOP への扉を開く:コンテナー
■ 親クラスのメソッドを再定義する
新しいクラスを定義するときに、親クラスのメソッドを再定義する意義について考察します。
class Replace(Piyo): def happy(self): print("Yes, as happy as happy can be!")
クラス Replace は、既存のクラス Piyo を親に持ち、既存のメソッド hello を再定義しています。
■ クラスオブジェクト
クラスも「呼び出し可能オブジェクト」なので、演算子 () を利用できます。
>>> p3 = Replace(); p3
<__main__.Replace object at 0x135bb30>
クラスオブジェクト Replace に演算子 () を適用すると、新たなインスタンスオブジェクトを生成します。変数 p3 は、生成した(クラス Replace の)インスタンスオブジェクトを束縛します。対話モードでは、式 p3 を評価すると、変数 p3 が束縛するオブジェクトに固有の識別情報が出力されます。すると、p3 は(Piyo ではなく)Replace のインスタンスオブジェクト __main__.Replace object で、固有の識別情報 0x135bbd0 を持つのが分かります。この識別情報は、その状況(実行環境)ごとに値が異なります。
>>> p3.happy()
Yes, as happy as happy can be!
式 p3.happy() を評価すると、インスタンスオブジェクト p3 が属するクラス Replace で再定義したメソッド happy を呼び出します。すると、メソッド happy の本体に記述したコードの断片を実行して、文字列 "Yes, as happy as happy can be!" を出力します。
■ 演算子:in
演算子 in を利用すると、指定したキーがメソッド辞書に含まれるかが分かります。
>>> "happy" in Replace.__dict__ True >>> "happy" in Piyo.__dict__ True
インスタンスオブジェクト p3 が属するクラス Replace のメソッド辞書には、キー要素 "happy" が含まれます。また、その親クラス Piyo のメソッド辞書にも、キー要素 "happy" が含まれます。そのため、メソッド呼び出し p3.happy() に呼応する関数オブジェクトは、(クラス Piyo ではなく)クラス Replace のメソッド辞書に帰結します。なぜなら、Piyo.__dict__["happy"] を検索する前に、Replace.__dict__["happy"] が見つかるからです。そのため、同じメソッド呼び出し happy() に対して、同じ親クラス Piyo の子孫でも、(Inherit) p2 と (Replace) p3 では異なる動作をします。
■ 特殊属性:__func__
特殊属性 __func__ を参照すると、そのメソッドオブジェクトが保持する、関数オブジェクトが得られます。
> >>> hex(id(p3.happy)) '0x124e620' インスタンスオブジェクトも(他のオブジェクトと同様に)属性を介して、他のオブジェクトを参照できます。ただし、インスタンスオブジェクト p3 が、インスタンス属性 happy を持つものの、特殊属性 __func__ を介さないと、関数オブジェクトは得られません。そのため、p3.happy という表現は、p3.__class__.__dict__["happy"] の簡略表記(近道)と見なせます。>>> p3.__class__.__dict__["happy"] >>> p3.happy() Yes, as happy as happy can be! >>> p3.__class__.__dict__["happy"](p3) Yes, as happy as happy can be!関数オブジェクト p3.happy(束縛メソッド)は「呼び出し可能オブジェクト」なので、演算子 () を適用できます。ただし、非束縛メソッド関数は、実引数 p3 が必要になります。