質問
Pythonでは、x.y
と書いた場合、x
のオブジェクトツリーを探索し、属性y
を探すと書籍で学びました。(見つからない場合は「AttributeError
となる」とありました。)
その際、以下のコードにおいてクラスA
が備える変数num
はインスタンスx
から参照できるのに対し、同じくクラスAが備える__base__
が参照できない理由が分からず困っています。
Python
1class A(): 2 num = 500 3 4x = A() 5print(hasattr(A,"num")) #⇒ True 6print(hasattr(x,"num")) #⇒ True 7 8print(hasattr(A,"__base__")) #⇒ True 9print(hasattr(x,"__base__")) #⇒ False(numと同じくクラスが備えているはずなのにFalseの理由が分からず…) 10 11print(x.num) #⇒ 500 12print(x.__base__) #AttributeError: 'A' object has no attribute '__base__'(numと同じくクラスが__base__を備えているはずなのにエラー)
調べたこと
この事象と関係あるかは分かりませんが、調べていたところ公式ドキュメントに
属性アクセスのデフォルトの振る舞いは、オブジェクトの辞書の属性の取得、設定、削除です。例えば a.x は、まず a.dict['x']、それから type(a).dict['x']、さらに type(a) のメソッド探索順序に従ったさらなる探索へと連鎖します。
デスクリプタ HowTo ガイド
とありました。
そこで、今回はx.__base__
でAttributeError
が発生したため、試しに以下の書き方をしてみました。
Python
1class A(): 2 num = 500 3 4x = A() 5print(A.__base__) #⇒ <class 'object'> 6print(type(x).__base__) #⇒ <class 'object'> 7print(type(x).__dict__['__base__']) #⇒ KeyError: '__base__'
type(x).__dict__['__base__']
はエラーとなりました。
たしかにtype(x).__dict__
の中を覗くと__base__
は存在しません。
Python
1class A(): 2 num = 500 3 4x = A() 5print(type(x).__dict__.keys()) #⇒ dict_keys(['__module__', 'num', '__dict__', '__weakref__', '__doc__'])
これは、以下の理解でよいのでしょうか。
・x
は__base__
を備えていないため、クラスオブジェクト及びクラスが継承するオブジェクトが__base__
を備えていないか探索していく
・探索では、オブジェクトの__dict__
の中を探していく
・今回、クラスA
は__base__
を備えているが、それは__dict__
の中には存在しないため、見つからなかったことになる。
・クラスA
は、クラスObject
を継承しているため、Object
の__dict__
の中にも__base__
があるか探すが、存在せず見つからなかったことになる。
・クラスObject
の__dict__
まで探して見つからなかったので、これ以上探索先は無い(※)ため、AttributeError
で終了する。
(※)x
が__getattr__
を備えている場合はそれを呼び出す。
単純すぎる理解と承知の上ですが、この程度しか思いつかず申し訳ありません。
初歩的な質問で大変恐縮ですが、冒頭のコードでx.__base__
がAttributeError
になってしまう理由を教えていただけますと幸いです。
よろしくお願いいたします。

回答2件
あなたの回答
tips
プレビュー