【问题标题】:Getting an attribute of grandparent class using getattr使用 getattr 获取祖父母类的属性
【发布时间】:2018-06-07 15:13:55
【问题描述】:

我正在尝试从ClassB 的实例访问Base 类的实例属性(inst_baseA / inst_baseB),具体取决于实例的属性(对象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'

这是我首先尝试的:

>>> 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(getattr(b, 'node'), b.x)
'base_A'

出于好奇:除了对getattr 进行两次 调用之外,还有其他方法可以从孙子类中获取 Base 类的属性吗?


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

所以我的代码实际上类似于:getattr(self, 'node.{}'.format(self.x))。我第一次没有正确解释它,希望现在更有意义。

【问题讨论】:

  • getattr(b.node, 'inst_base') 或者更简单的b.node.inst_base?
  • @MSeifert 我更新了我的问题以反映我的情况。我第一次没有做对:)
  • 为什么不只是getattr(self.node, self.x)
  • @Aran-Fey 这行得通.. 不知道我自己怎么没看到。非常感谢

标签: python inheritance


【解决方案1】:

operator.attrgetter,但确实不是这种东西的意思,所以语法很尴尬:

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

但这真的很不直观,所以为了避免让阅读您的代码的人感到困惑,最好使用您自己的 multi-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'

【讨论】:

  • 谢谢。我已经更新了我的问题以更好地反映我的情况。请检查一下好吗?
【解决方案2】:

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

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

node.inst_base 不是b 的属性,但是:

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

因此,每个“嵌套”级别都需要一个 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'

或者,更进一步,您可以创建一个使用“嵌套”属性名称的 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 的建议。

【讨论】:

    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-18
    • 2010-12-16
    相关资源
    最近更新 更多