Search code examples
pythonpython-3.xgetattr

can't access an attribute's attribute w getattr?


Based on

In [65]: %paste
class Thing(object):
    def __init__(self, obj):
        self.legs = 4
        self.obj = obj
    def length(self):
        return 6

class Thing2(object):
    def __init__(self):
        self.arms = 2

## -- End pasted text --

In [66]: t = Thing2()

In [67]: x = Thing(t)

In [68]: x.obj.arms
Out[68]: 2

In [69]: %paste
def set_session_attribute(obj, attribute):
    if attribute.endswith('()'):
        attribute = attribute.replace('()', '')
        return getattr(obj, attribute)()
    else:
        return getattr(obj, attribute)

## -- End pasted text --

In [70]: x = set_session_attribute(x, 'obj.arms')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-70-f8cbad3c39e5> in <module>()
----> 1 x = set_session_attribute(x, 'obj.arms')

<ipython-input-69-65b6efa81583> in set_session_attribute(obj, attribute)
      4         return getattr(obj, attribute)()
      5     else:
----> 6         return getattr(obj, attribute)

AttributeError: 'Thing' object has no attribute 'obj.arms'

How can I use getattr to find arms of the t object in one line? Thank you

class Thing(object):
    def __init__(self, obj):
        self.legs = 4
        self.obj = obj

    def length(self):
        return 6

class Other(object):
    def __init__(self):
        self.arms = 2

    def length(self):
        return 5


def set_session_attribute(obj, attribute):
    attrs = attribute.split('.')
    for attribute in attrs:
        if attribute.endswith('()'):
            attribute = attribute.replace('()', '')
            obj = getattr(obj, attribute)()
        else:
            obj = getattr(obj, attribute)
    return obj

a = Other() # other has attr or function too
b = Thing(a) # thing has other obj, attr, and its own function

"""
In [80]: b.obj.length()
Out[80]: 5

In [81]: b.obj.arms
Out[81]: 2

In [83]: b.length()
Out[83]: 6

In [84]: b.legs
Out[84]: 4
"""

g = set_session_attribute(b, 'obj.length()')
h = set_session_attribute(b, 'obj.arms')
i = set_session_attribute(b, 'length()')
j = set_session_attribute(b, 'legs')
assert g == 5
assert h == 2
assert i == 6
assert j == 4

Solution

  • You can try this:

        def set_session_attribute(obj, attribute):
            if attribute.endswith('()'):
                attribute = attribute.replace('()', '')
            attrs = attribute.split('.')
            for attr in attrs:
                obj = getattr(obj, attr)
            return obj