LoginSignup
41
38

More than 5 years have passed since last update.

[python] class内での変数とself.変数の違い

Posted at

instance.name

クラス変数を呼び出すとき、instance.nameで呼び出すが、
その呼出先には2種類ある。

name
class foo:
    name1 = 'test1'
    def __init__(self):
        self.name2 = 'test2'

bar = foo()
print(bar.name1)
# => test1
print(bar.name2)
# => test2

この2つは同じように値を変更することができる。

bar.name1 = 'huga'
bar.name2 = 'hogehoge'
print(bar.name1)
# => huga
print(bar.name2)
# => hogehoeg

ところが、次のようにすると挙動が変わる。

print(bar.__class__.name1)
# => test1
print(bar.__class__.name2)
# => AttributeError

この原因は何か。実はクラスが持つ変数には2種類存在する。
一つは普通のクラス変数。
もう一つはクラスの基本メンバーとして存在するdictの変数。

name
class foo:
    name1 = 'test1'
    def __init__(self):
        self.name2 = 'test2'

bar = foo()
print(bar.__dict__)
# => {'name2':'test2'}
bar.name1 = 'hoge'
print(bar.__dict__)
# => {'name2':'test2','name1':'hoge'}

instance.nameといった呼び出し方は優先的に__dict__[name]を表示する。
__dict__[name]が存在しなかった場合のみ、__class__.nameを呼び出す。

もしクラス変数を初期値や非変更値として使いたいなら、name1のようにself.を使わずに書くべきだろう。
また、常にクラス内で規定した値で処理を行いたいのならばself.class.nameなどとして呼び出すべきだろう。
name1のように書くメリットとして、初期値に戻せるというのもある。

name
class foo:
    name1 = 'test1'
    def __init__(self):
        self.name2 = 'test2'

bar = foo()
print(bar.name1)
# => test1
bar.name1 = 'newname'
print(bar.name1)
# => newname
del bar.name1
print(bar.name1)
# => test1

self.nameと宣言するのは、それが変更されることを前提としていたり、変更前の値を覚えておく必要が無い時だけかもしれない。

41
38
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
41
38