初めてのPython(24章後編)

名前空間 = ディクショナリ

サブクラスにスーパークラスの属性が継承される時に起こるのは「ディクショナリのリンク」

[kobakoba0723@fedora13-intel64 ~]$ cat namespace.py
#!/usr/bin/env python

class C1(object):
  c1_data = 1
  def __init__(self, value):
    self.name = value
  def printname(self):
    print self.name

class C2(object):
  c2_data = 2
  def __init__(self, value):
    self.age = value
  def printage(self):
    print self.age

class C3(C1, C2):
  def __init__(self, name, age, tel):
    C1.__init__(self, name)
    C2.__init__(self, age)
    self.tel = tel
  def printdata(self):
    self.printname()
    self.printage()

class C4(C2, C1):
  def __init__(self, name, age, address):
    C1.__init__(self, name)
    C2.__init__(self, age)
    self.address = address
  def printdata(self):
    self.printname()
    self.printage()

if __name__ == '__main__':
  x = C3('taro', 28, '012-3456-7890')
  y = C4('jiro', 28, 'Japan')
  
  print 'x.__class__', x.__class__
  print 'x.__dict__:', x.__dict__
  print 
  
  print 'y.__class__:', y.__class__
  print 'y.__dict__:', y.__dict__
  print 
  
  print '[C1.__bases__]'
  print '\t',C1.__bases__
  print '[C2.__bases__]'
  print '\t',C2.__bases__
  print '[C3.__bases__]'
  print '\t',C3.__bases__
  print '[C4.__bases__]'
  print '\t',C4.__bases__
  print 
  
  print '[C1.__dict__]'
  for key in C1.__dict__.keys():
    print '\t(key, value) = (%s, %s)' %  (key, C1.__dict__[key])
  print '[C2.__dict__]'
  for key in C2.__dict__.keys():
    print '\t(key, value) = (%s, %s)' %  (key, C2.__dict__[key])
  print '[C3.__dict__]'
  for key in C3.__dict__.keys():
    print '\t(key, value) = (%s, %s)' %  (key, C3.__dict__[key])
  print '[C4.__dict__]'
  for key in C4.__dict__.keys():
    print '\t(key, value) = (%s, %s)' %  (key, C4.__dict__[key])
  print 
  
  print 'x.name:', x.name
  print 'x.tel:', x.tel
  print 'x.c1_data:', x.c1_data
  print 'x.c2_data:', x.c2_data

[kobakoba0723@fedora13-intel64 ~]$ python namespace.py
x.__class__ <class '__main__.C3'>
x.__dict__: {'age': 28, 'tel': '012-3456-7890', 'name': 'taro'}

y.__class__: <class '__main__.C4'>
y.__dict__: {'age': 28, 'name': 'jiro', 'address': 'Japan'}

[C1.__bases__]
	(<type 'object'>,)
[C2.__bases__]
	(<type 'object'>,)
[C3.__bases__]
	(<class '__main__.C1'>, <class '__main__.C2'>)
[C4.__bases__]
	(<class '__main__.C2'>, <class '__main__.C1'>)

[C1.__dict__]
	(key, value) = (__module__, __main__)
	(key, value) = (c1_data, 1)
	(key, value) = (printname, <function printname at 0x7fd9b0dcec08>)
	(key, value) = (__dict__, <attribute '__dict__' of 'C1' objects>)
	(key, value) = (__weakref__, <attribute '__weakref__' of 'C1' objects>)
	(key, value) = (__doc__, None)
	(key, value) = (__init__, <function __init__ at 0x7fd9b0dceb90>)
[C2.__dict__]
	(key, value) = (__module__, __main__)
	(key, value) = (printage, <function printage at 0x7fd9b0dcecf8>)
	(key, value) = (__dict__, <attribute '__dict__' of 'C2' objects>)
	(key, value) = (c2_data, 2)
	(key, value) = (__weakref__, <attribute '__weakref__' of 'C2' objects>)
	(key, value) = (__doc__, None)
	(key, value) = (__init__, <function __init__ at 0x7fd9b0dcec80>)
[C3.__dict__]
	(key, value) = (__module__, __main__)
	(key, value) = (printdata, <function printdata at 0x7fd9b0dcede8>)
	(key, value) = (__doc__, None)
	(key, value) = (__init__, <function __init__ at 0x7fd9b0dced70>)
[C4.__dict__]
	(key, value) = (__module__, __main__)
	(key, value) = (printdata, <function printdata at 0x7fd9b0dceed8>)
	(key, value) = (__doc__, None)
	(key, value) = (__init__, <function __init__ at 0x7fd9b0dcee60>)

x.name: taro
x.tel: 012-3456-7890
x.c1_data: 1
x.c2_data: 2
[kobakoba0723@fedora13-intel64 ~]$ 

オブジェクトツリーの検索が、「リンクされたディクショナリに対して順に行う」ってことだったから、
x.__dict__/y.__dict__ で age/name の出力順が入れ替わってると期待したけど、
ちゃんと考えるとディクショナリなんだから、順番には意味がないんだった。
だから、たとえ入れ替わってたとしても”たまたま”そうなったってことにしかならない。


とはいえ、__bases__属性の結果はスーパークラスとして指定した順にちゃんと並んでる。
ここをどうにかして使うんだろうなぁ。


あと、サブクラスのインスタンス属性なのか、スーパークラスインスタンス属性なのかの見分けもどうやってるんだろう。
インスタンスオブジェクトの__dict__を見ただけだと、どっちも同格のものとして見えてしまう。
それに、.__class__.__dict__にはサブクラスのインスタンス属性は現れない。
当然、.__bases__[N].__dict__にもスーパークラスインスタンス属性は現れない