8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ドットによるオブジェクトの属性の取得をカスタマイズするための__getattr__と__getattribute__

Posted at

.による属性の取得

class文内で定義した、変数やメソッドといったオブジェクトの属性は、普通.で取得すると思います。例えば次のようなクラスを定義したとします。

class Foo:
    def __init__(self):
        self.foo = "foo"
        self.bar = "bar"

Fooのインスタンスfooの属性foobar.で取得することができます。

>>> foo = Foo()
>>> foo.foo
'foo'
>>> foo.bar
'bar'

この.による動作は特別な属性である__getattr____getattribute__メソッドを用いてカスタマイズすることができます。

__getattr__によるカスタマイズ

__getattr__を定義すると、.で属性を取得しようとした時に、通常の名前検索をまず行って、それでも指定された属性が見つからない場合、__getattr__が呼ばれ、返された値をその属性として返します。

次のクラスFooは、__getattr__をメンバ変数fooを常に返すように定義しています。

class Foo:

    def __init__(self):
        self.foo = "foo"
        self.bar = "bar"
    
    def __getattr__(self, name):
        return self.foo

Fooのインスタンスfooは、self.barというメンバ変数を持つので、foo.barでは、self.barが返されますが、self.anythingというメンバ変数は無いのでself.__getattr__("anything")が実行され、self.foo(すなわち文字列"foo")が返されています。

>>> foo = Foo()
>>> foo.foo
'foo'
>>> foo.bar
'bar'
>>> foo.anything
'foo'

__getattribute__によるカスタマイズ

__getattribute__が定義されていた場合、.で属性を取得しようとすると常にこのメソッドが呼ばれます。__getattribute__の定義の中では、.を用いてそのオブジェクトの属性を取得しようとすると、自分自身の__getattribute__が再帰的に呼ばれてしまうため、それを避けるためにスーパークラスobject__getattribute__を使用します。

class Bar:

    def __init__(self):
        self.foo = "foo"
        self.bar = "bar"
    
    def __getattribute__(self, name):
        return object.__getattribute__(self, "foo")

次の実行結果を見るとわかるように、Barのインスタンスbarは、self.barというメンバ変数を持っているにも関わらず、bar.barとしても__getattribute__によりself.foo(すなわち文字列"foo")が返されています。

>>> bar = Bar()
>>> bar.foo
'foo'
>>> bar.bar
'foo'
>>> bar.anything
'foo'

組み込み関数getattrhasattr

組み込み関数getattrhasattrは、__getattr____hasattr__でカスタマイズされた属性取得に基づきます。ですので、getattrでオブジェクトの属性を取得するのと.で取得するのは同じことです。上の例でのFooBarのインスタンスで確かめると出力はこうなります。

>>> getattr(foo, "bar")
'bar'
>>> getattr(bar, "bar")
'foo'

__getattr____getattribute__がどんな属性を指定しても値を返す(つまりAttributeErrorが発生しない)のであれば、hasattrは常にTrueを返します。

>>> hasattr(foo, "anything")
True
>>> hasattr(bar, "anything")
True
8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?