TL;DR
Python は動的型付き言語なので、プログラム実行中にオブジェクトの属性を追加したり、削除することができる。getattr()は、オブジェクトの属性の値を返す組み込み関数である。メソッド名を入力せずに、文字列の内容を元にメソッドを呼び出すことが可能である。
getattr() のポイント
getattr(object, name[, default])
第一引数の object にはオブジェクト名、第二引数 name には属性を指定する。属性が存在しない場合はデフォルト値 default を返す。
- オブジェクトの属性の値を返す
- インスタンス変数だけでなく、メソッドも取得できる
- 第二引数は'文字列'でなくてはならない
- 第二引数に組み込み関数を指定し適用できる
- getattr(a, 'b') は a.b と等価である
- ループで使うことができる
公式には以下のように記載されている。
object の指名された属性の値を返します。 name は文字列でなくてはなりません。文字列がオブジェクトの属性の一つの名前であった場合、戻り値はその属性の値になります。 例えば、 getattr(x, 'foobar') は x.foobar と等価です。指名された属性が存在しない場合、 default が与えられていればそれが返され、そうでない場合には AttributeError が送出されます。
getattr() - 組み込み関数 — Python 3.9.4 ドキュメント
setattr() で属性を設定し、getattr()で属性を取り出す
以下は、setattr() を用いてクラス A の属性に値をセットして、getattr() で値を返している。
class A:
pass
a = A()
setattr(a, 'txt','x')
setattr(a, 'No', 2)
getattr(a, 'txt') # 'x'
getattr(a, 'No') # 2
第三引数にデフォルト値を指定する
属性が存在しない場合は AttributeError になるので、第三引数にデフォルト値を指定してみよう。
class A:
name = 'Taro'
a = A()
a.name # 'Taro'
getattr(a, 'name') # 'Taro'
# getattr(a, 'mail') # 属性が存在しない場合はAttributeErrorになる
getattr(a, 'mail', 'Gmail') # 第三引数にデフォルト値を指定する 'Gmail'
メソッドの取得
すべてのテキストを大文字にする upper()メソッドを取得してみる。getattr() の第二引数に upper()を指定すると、txt.upper() と同じになる。
txt = 'abcde'
a = getattr(txt, 'upper')
a() # 'ABCDE'
# txt.upper() と同じ結果を返している
メソッドに引数を指定
メソッドに引数を指定する場合、getattr(クラス名, 'メソッド名')('引数')のように書くとよい。
class A:
name = 'Taro'
def hoge(self, b):
print(b)
a = A()
getattr(a, 'name') # 'Taro'
getattr(a, 'hoge')('hello') # hello
例外
例外を適用してみる。
class a():
def japan(self):
print ('こんにちは')
def english(self):
print ('hello')
def unknown(self):
print ('何語ですか?')
def hello(lang):
try:
getattr(a(),lang)()
except:
getattr(a(),'unknown')()
hello('japan') # こんにちは
hello('english') # hello
hello('german') # 何語ですか?
ループで使う
メソッドの反復処理を行うこともできる。以下は、メソッドをリストに入れて for 文で順に処理を実行している例。
class A:
def add(self, x, y):
return x + y
def sub(self, x, y):
return x - y
a = A()
for i in ['add', 'sub']:
f = getattr(a, i)(1, 2)
print(f)
# 3
# -1