Pythonのインスタンス変数にアクセスするとき、変数名を文字列で指定して取得したいときがあります。
この記事ではそんな実装をPythonの標準機能で実現する方法を解説しています。
クラスでの変数の扱い方(復習)
インスタンス変数とクラス変数
クラスを扱ううえで、登場する変数は「インスタンス変数」と「クラス変数」の2つあります。
本記事はインスタンス変数の話ですが「まだ区別がつかないよ!」という人向けに、まずはかんたんに解説。
インスタンス変数ってなに?
インスタンス変数は文字通りインスタンスごとに独立した変数です。
以下のように設定、取得ができます。
self.変数名 = 値 # 値を設定
self.変数名 # 変数から値を取得
クラス内のメソッドからインスタンス変数にアクセスするときには、必ずselfを付けてあげます。
selfはそのインスタンスそれ自身を指しているので、他のインスタンスを参照したりするのはできません。
かんたんに使い方を示すと以下のようになります。
class MyClass():
def __init__(self): # インスタンスを初期化するときに自動で呼ばれる
self.val = "This is A" #インスタンス変数 val を設定
def get_val(self):
return self.val #インスタンス変数 val を返す
def print_val(self):
print(self.val) #インスタンス変数 val を画面に出力
c = MyClass() #クラスMyClassのインスタンスを作る
#(ここで初期化__init__()が呼ばれて
# self.valに値が入る)
print(c.val) # "This is A"
print(c.get_val()) # "This is A"
c.print_val() # "This is A"
下の3行は同じ結果になります。
container.valのように直接インスタンス変数にアクセスするのが気持ち悪いときは、container.get_val() みたいにインスタンス変数にアクセスするためだけのメソッド(アクセサ)を定義します。
値をセットするときは以下のようになります。
container.set_val("This is B")
container.val = "This is B"
container.print_val() # “This is B”
クラス変数ってなに?
インスタンス変数はインスタンスごとに独立した存在でしたが、クラス変数は全てのインスタンスに共通する変数です。クラス変数にアクセスするだけなら、インスタンスを生成する必要すらありません。
つまり、こういうクラスがあるときは
class MyClassB():
val = 1 # これがクラス変数
def do_something(self):
print(MyClassB.val)
こんな感じでクラス変数にアクセスします。
print(MyClassB.val) # 1
c = MyClassB()
c.do_something() # 1
上のprint文と、下の2行は同じ結果になります。
クラス変数にはselfを付けません。
クラス変数は、変数として使うだけでなく、定数を定義するときによく使います。
インスタンス変数に文字列でアクセスする(結論)
インスタンス名.変数名でかんたんにインスタンス変数にアクセスできるのですが、「インスタンス変数名を文字列で指定して動的なアクセスをしたい」ときが(時々)あります。
これは実はPythonの標準機能で実現できます。
インスタンス変数を文字列で指定して取得する
getattr() を使います。
組み込み関数なので、importなどは必要ありません。
val = getattr(インスタンス, “変数名”)
このようなクラスがあるとき
class MyClassC():
def __init__(self):
self.val_a = "This is A"
self.val_b = "This is B"
インスタンス変数 val_a の値を取得したいときは
c = MyClassC()
b = getattr(c, 'val_a') # インスタンス変数 val_a を取得
print(b) # "This is A"
print(c.val_a) # "This is A"
このような感じで文字列を指定してインスタンス変数の中身を取り出せます。
もちろん、文字列の部分は任意の変数に置き換えてもOK。
インスタンス変数を文字列で指定して定義する
setattr() を使います。
こちらも組み込み関数。
setattr(インスタンス,"変数名", 値)
上のクラスの例だと、
setattr(c, 'val_c', "This is C")
print(c.val_c) # "This is C"
Pythonのスキルを使って毎月の収入源を増やすのが最適なんじゃないかという件
実際、今のスキルに合わせて仕事を獲得し、スキマ時間で毎月+5、+20、+70万円くらいの人が多いです。
必要なスキル、仕事の獲得までの流れは以下の記事で徹底解説しています。
(もちろん全部無料です)
空いた時間にぜひ参考にしてみてください。
すべてのインスタンス変数名を文字列として取得
上記に関連して、知っておくと便利な機能を紹介。
インスタンスに紐付いているすべてのインスタンス変数を取得するにはどうしたらいいでしょうか?
__dict__ プロパティを使います。
これを使うと、すべてのインスタンス変数名を文字列で取得することもできます。
class MyClassC():
def __init__(self):
self.val_a = "This is A"
self.val_b = "This is B"
c = MyClassC()
dict_vals = c.__dict__ # インスタンス c の要素を全て取得
pprint.pprint(dict_vals, indent=1, width=40)
# {'val_a': 'This is A',
# 'val_b': 'This is B'}
まとめ
Pythonでインスタンス変数に文字列を指定してアクセスする方法を解説しました。
柔軟な方法で、しかもとてもかんたんに、インスタンス変数にアクセスできるのが確認できました。
Pythonの自由度の高い言語仕様を生かして、ぜひプログラミングを楽しんでください!