読者です 読者をやめる 読者になる 読者になる

SDN開発エンジニアを目指した活動ブログ

〜SDNなオープンソース製品を実際に使って試してみる〜

Python勉強メモ:特殊メソッド__getattribute__とは?

Pythonを勉強しているなかで、特殊メソッド__getattribute__に遭遇したので、ちょっと調べてみた。
どうやら、__getattribute__のほかにも、__getattr__なるものがあるらしい。
・__getattr__:未定義のメンバーにアクセスする際に呼び出される。
・__getattribute__:未定義・定義済み関わらず、すべてのメンバーアクセスで呼び出される。

◆特殊メソッド __getattribute__

まずは、__getattribute__サンプルとして、test_getattribute.py で試してみた。

import sys

class A(object):
    def __init__(self):
        print "aaa0"
    def a1(self):
        print "aaa1"

class B(A):
    def __init__(self):
        print "bbb0"
    def b1(self):
        print "bbb1"
    def __getattribute__(self,name):
        try:
            print "getattribute:name=%s"%name
            return object.__getattribute__(self, name)
        except:
            print "undefined method"
            sys.exit()

if __name__ == '__main__':
    t1=B()
    t1.b1()
    print "------"
    t2=B()
    t2.a1()
    print "------"
    t3=B()
    t3.c1()

test_getattribute.py を動かしてみた。

$ python test_getattribute.py 
bbb0
getattribute:name=b1
bbb1
------
bbb0
getattribute:name=a1
aaa1
------
bbb0
getattribute:name=c1
undefined method

継承クラス関係のいずれのメソッドにアクセスした場合でも、必ず、__getattribute__が呼び出されているし、
さらに、未定義メソッドにアクセスした場合でも、__getattribute__が呼び出されている様子がわかると思います。

◆特殊メソッド __getattr__

つぎに、__getattr__サンプルとして、test_getattr.py で試してみた。

import sys

class A(object):
    def __init__(self):
        print "aaa0"
    def a1(self):
        print "aaa1"

class B(A):
    def __init__(self):
        print "bbb0"
    def b1(self):
        print "bbb1"
    def __getattr__(self,name):
        try:
            print "getattr:name=%s"%name
            return object.__getattr__(self, name)
        except:
            print "undefined method"
            sys.exit()

if __name__ == '__main__':
    t1=B()
    t1.b1()
    print "------"
    t2=B()
    t2.a1()
    print "------"
    t3=B()
    t3.c1()

test_getattr.py を動かしてみた。

$ python test_getattr.py 
bbb0
bbb1
------
bbb0
aaa1
------
bbb0
getattr:name=c1
undefined method

単に、未定義メソッドにアクセスした場合に限り、__getattr__が呼び出されている様子がわかると思います。

◆おわりに

継承クラス関係における子クラスで、__getattribute__を定義しておけば、いずれのメソッドへのアクセスが発生したのかを一元的に観測できるようになる。確かに便利そうだと理解できた。