初めてのPython(22章)

クラスとインスタンス

クラスはインスタンスを作るためのひな形。
クラスを作成(定義)するには class ステートメントを使い、インスタンスを作成するにはクラスを呼び出す。


インスタンスの属性検索は以下のようにして行われる

  • 下から上に(サブクラスの属性を検索後、スーパークラスの属性を検索)
  • 左から右に(同一階層のクラスでは、定義時に左に指定したスーパークラスから順に検索)
[kobakoba0723@fedora13-intel64 ~]$ cat mk_class.py
#!/usr/bin/env python

class C1(object):
  x = 1
  z = 2

class C2(object):
  w = 3
  z = 4

class C3(C1, C2):
  x = 5
  y = 6
  
  def __init__(self, name):
    self.name = name

class C4(C2, C1):
  x = 7
  y = 8
  
  def __init__(self, name):
    self.name = name

I1 = C3('taro')
I2 = C4('jiro')

print '(I1.x, I1.y, I1.z, I1.w, I1.name) = (%d, %d, %d, %d, %s)' % (I1.x, I1.y, I1.z, I1.w, I1.name)
print '(I2.x, I2.y, I2.z, I2.w, I2.name) = (%d, %d, %d, %d, %s)' % (I2.x, I2.y, I2.z, I2.w, I2.name)

[kobakoba0723@fedora13-intel64 ~]$ python mk_class.py
(I1.x, I1.y, I1.z, I1.w, I1.name) = (5, 6, 2, 3, taro)
(I2.x, I2.y, I2.z, I2.w, I2.name) = (7, 8, 4, 3, jiro)

x,y,z,w はクラス属性として扱われ、nameはインスタンス属性として扱われる
classステートメントの中で直接値を代入する(クラス属性)か、selfを経由して値を代入する(インスタンス属性)かで決まる。

クラス属性にアクセスするには、

<インスタンス>.<属性>とやるだけでは、クラス属性にはアクセスできない。
スーパークラスのクラス属性にアクセス出来るかと思って、<クラス>.<属性>ってやっても何も変わらなかったので(指定した属性は、スーパークラスの属性)<クラス>.__class__.<属性>ってやったら怒られた。
スーパークラスのクラス属性にはアクセスできない or 方法が違うらしい

[kobakoba0723@fedora13-intel64 ~]$ python
Python 2.6.4 (r264:75706, Apr  1 2010, 02:55:51) 
[GCC 4.4.3 20100226 (Red Hat 4.4.3-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mk_class import *
(I1.x, I1.y, I1.z, I1.w, I1.name) = (5, 6, 2, 3, taro)
(I2.x, I2.y, I2.z, I2.w, I2.name) = (7, 8, 4, 3, jiro)
>>> I1.__class__
<class 'mk_class.C3'>
>>> I2.__class__
<class 'mk_class.C4'>
>>> I1.w, I2.w, C3.w, C4.w, C2.w
(3, 3, 3, 3, 3)
>>> I1.w = 10
>>> I1.w, I2.w, C3.w, C4.w, C2.w
(10, 3, 3, 3, 3)
>>> I2.__class__.w = 20
>>> I1.w, I2.w, C3.w, C4.w, C2.w
(10, 20, 3, 20, 3)
>>> C3.w = 30
>>> I1.w, I2.w, C3.w, C4.w, C2.w
(10, 20, 30, 20, 3)
>>> 
>>> C3.__class__
<type 'type'>
>>> C3.__class__.w
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'type' has no attribute 'w'
>>>

その他

継承:より一般的な物事に対応するクラスから特性を受け継ぐこと
コンポジション:独自の機能をもつ要素を組み合わせて新しいものを作ること