如果object是某个其他对象的属性,如何使用与name对应的字符串来访问对象的attrbute

时间:2016-10-06 12:18:33

标签: python

我有3个课程如下: -

class C(object):
    def __init__(self, v):
        self.var = v

class B(object):
    def __init__(self, c):
        self.c = c

class A(object):
    def __init__(self, b):
        self.b = b

I have created instances as 
c = C("required result")
b = B(c)
a = A(b)

>>> a.b.c.var
'required result'

现在我需要将b.c.var作为字符串传递给某个函数,并获取类似于sample函数的var值,如下所示 -

`sample(a, 'b.c.var')` should return 'required result'`

什么应该是pythonic方式来实现这一目标 这是我的尝试: -

for attr in ('b', 'c', 'var'):
    a = getattr(a, attr)
>>> print a
required result

2 个答案:

答案 0 :(得分:5)

您可以使用带有点名称表示法的operator.attrgetter,例如:

from operator import attrgetter
attrgetter('b.c.var')(a)
# 'required result'

然后,如果您不喜欢该语法,请使用它来制作sample函数,例如:

def sample(obj, attribute):
    getter = attrgetter(attribute)
    return getter(obj)

从上面链接的文档中,operator.attrgetter使用以下代码的等效内容:

def attrgetter(*items):
    if any(not isinstance(item, str) for item in items):
        raise TypeError('attribute name must be a string')
    if len(items) == 1:
        attr = items[0]
        def g(obj):
            return resolve_attr(obj, attr)
    else:
        def g(obj):
            return tuple(resolve_attr(obj, attr) for attr in items)
    return g

def resolve_attr(obj, attr):
    for name in attr.split("."):
        obj = getattr(obj, name)
    return obj

事实上 - 您的原始代码只是尝试相当于resolve_attr ...

答案 1 :(得分:1)

我想这是更准确的方法。 (使用try-except构造):

...

c = C("required result")
b = B(c)
a = A(b)

def sample(obj, path):
    path_attrs = path.split('.')    # splitting inner attributes path
    inner_attr = None

    for p in path_attrs:
        try:
            inner_attr = getattr(inner_attr if inner_attr else  obj, p)
        except AttributeError:
            print('No %s field' % p)

    print(inner_attr)

sample(a, 'b.c.var')  # will output 'required result'