次のような文字列でクラスの属性を取得できることはわかっています。
object.attribute = 'foo'
x = 'attribute'
getattr(object, x)
>>> 'foo'
文字列を使用してオブジェクトの属性を「深く掘り下げる」方法はありますか? つまり、オブジェクトに別のオブジェクトが含まれている場合、サブオブジェクトの属性を文字列で取得するにはどうすればよいでしょうか? 例えば:
object.object.attribute
次のような文字列でクラスの属性を取得できることはわかっています。
object.attribute = 'foo'
x = 'attribute'
getattr(object, x)
>>> 'foo'
文字列を使用してオブジェクトの属性を「深く掘り下げる」方法はありますか? つまり、オブジェクトに別のオブジェクトが含まれている場合、サブオブジェクトの属性を文字列で取得するにはどうすればよいでしょうか? 例えば:
object.object.attribute
operator.attrgetter
関数はこれを行います:
class Foo: pass
f = Foo()
f.bar = Foo()
f.bar.baz = Foo()
f.bar.baz.quux = "Found me!"
import operator
print operator.attrgetter("bar.baz.quux")(f) # prints "Found me!"
このリンクにあるレシピが大好きです(実際には、コメントはさらに優れています)
Claudiuの回答から借用した例(これも素晴らしい):
class Foo: pass
f = Foo()
f.bar = Foo()
f.bar.baz = Foo()
f.bar.baz.quux = "Found me!"
ドットに続く再帰的な getattr:
>>> rgetattr = lambda o,a: reduce(getattr, a.split('.'), o)
>>> rgetattr(f, 'bar.baz.quux')
'Found me!'
非ラムダ版は次のとおりです。
def rgetattr(obj, attr):
return reduce(getattr, attr.split('.'), obj)
>>> class Foo: pass
>>> f = Foo()
>>> f.bar = Foo()
>>> f.bar.baz = Foo()
>>> f.bar.baz.quux = "Found me!"
>>> getattr(f, 'bar')
<__main__.Foo instance at 0x01EC5918>
>>> getattr(getattr(f, 'bar'), 'baz')
<__main__.Foo instance at 0x01EC5A30>
>>> getattr(getattr(getattr(f, 'bar'), 'baz'), 'quux')
'Found me!'
編集:簡単な方法として行われます:
>>> def dynamic_lookup(obj, dot_attrs):
attr_list = dot_attrs.split(".")
while attr_list:
obj = getattr(obj, attr_list.pop(0))
return obj
>>> f
<__main__.Foo instance at 0x01EC50A8>
>>> dynamic_lookup(f, 'bar.baz.quux')
'Found me!'
文字列のリストを取る ( のattr_list
代わりに直接取る) には簡単に適応できますが、文字列としての表記の方が見栄えdot_attrs
が良いと思いました....