使用getattr获取祖父母类的属性

时间:2018-06-06 15:28:35

标签: python inheritance

我尝试从inst_baseA / inst_baseB的实例访问Base类的实例属性(ClassB),具体取决于实例的属性({{1}对象ClassB)。

这是我的代码:

self.x

这是我先试过的:

class Base(object):
    def __init__(self):
        self.inst_baseA = 'base_B'
        self.inst_baseB = 'base_A'


class ClassA(object):
    def __init__(self):
        self.node = Base()


class ClassB(ClassA):
    def __init__(self):
        super(ClassB, self).__init__()
        self.x = 'base_A'

如果我将调用链接到getattr:

,我就克服了这个问题
>>> b = ClassB()
>>> getattr(b, 'node.inst_{}'.format(b.x))

Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    getattr(b, 'node.inst_{}'.format(b.x))
AttributeError: 'ClassB' object has no attribute 'node.inst_base_A'

出于好奇:除了对>>> getattr(getattr(b, 'node'), b.x) 'base_A' 进行两次调用之外,有没有办法从孙子类中获取Base类的属性?

更新:我需要它的原因是我试图: - 从祖父母类(inst_baseA或inst_baseB)获取属性 - 取决于我的实例上的属性(x的值)

所以我的代码实际上是:getattr。我第一次没有正确解释它,希望它现在更有意义。

2 个答案:

答案 0 :(得分:2)

根据[Python]: getattr(object, name[, default])

  

返回 object 的命名属性的值。 name 必须是字符串。如果字符串是对象属性之一的名称,则结果是该属性的值。例如,getattr(x, 'foobar')相当于x.foobar

node.inst_base 属于b,但是:

  • nodeb
  • 的属性
  • inst_baseb.node
  • 的属性

因此,您需要为每个&#34;嵌套&#34;进行一次getattr调用。水平。

考虑到我已将您的代码粘贴到解释器的交互式窗口中:

>>> getattr(b, 'node.inst_base')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'ClassB' object has no attribute 'node.inst_base'
>>>
>>> getattr(getattr(b, "node", None), "inst_base", None)
'base'

或者,为了更进一步,您可以创建一个与&#34;嵌套&#34;一起使用的getter。属性名称:

>>> def getattr_nested(obj, nested_attr):
...     attrs = nested_attr.split(".")
...     ret = obj
...     for attr in attrs:
...             ret = getattr(ret, attr, None)
...             if ret is None:
...                     return None
...     return ret
...
>>>
>>> getattr_nested(b, "node.inst_base")
'base'
>>> getattr_nested(b, "node.inst_base2")
>>> getattr_nested(b, "node")
<__main__.Base object at 0x0000021A2A593D30>

但这可能非常低效(而且,也没有处理角落案件),你最好使用@Aran-Fey的建议。

答案 1 :(得分:2)

operator.attrgetter,但它真的不适合这种事情,所以语法很尴尬:

>>> operator.attrgetter('node.inst_base')(b)
'base'

但这确实非常不直观,所以为了避免让阅读代码的人感到困惑,最好还是推出自己的多getattr:

def get_multi_attr(obj, attrs):
    for attr in attrs.split('.'):
        obj = getattr(obj, attr)
    return obj
>>> get_multi_attr(b, 'node.inst_base')
'base'