【问题标题】:hasattr for nested attributeshasattr 用于嵌套属性
【发布时间】:2014-07-16 11:21:04
【问题描述】:

我需要这样的东西(伪代码):

if hasattr(object, 'detail.infotext')

我的意思是我想检查对象是否有属性details,如果有,那么details 是否有一个名为infotext 的属性

我可以这样做:

if hasattr(object, 'detail'):
    if hasattr(object.detail, 'infotext'):
        do something

但单行字更容易阅读。

【问题讨论】:

  • if hasattr(object, 'detail') and hasattr(object.detail, 'infotext'):?惰性求值意味着第二个 hasattr 只有在第一个是 True 时才会被调用。

标签: python


【解决方案1】:

我知道这并不是你真正想要做的,但无论如何它更像是 Python (如果你知道你要明确寻找的属性的名称):

try:
   do something with object.detail.infotext
except AttributeError:
   do something else
【解决方案2】:

假设您想实际使用您的属性值,operator.attrgetter(在 Python 2.6+ 中)也可能有用。你仍然需要捕获一个异常,除此之外它非常简单:

from operator import attrgetter

try:
   print attrgetter("detail.infotext")(object)
except:
   <handle exception>

【讨论】:

    【解决方案3】:

    未经测试,但应该可以工作:

    def hasattrpath(obj, path):
        parts = path.split(".")
        for part in parts:
            if hasattr(obj, part):
                obj = getattr(obj, part)
            else:
                return False
        else:
            return True
    

    但是,除非您在代码库中到处都有这样的测试,并且使用深度嵌套的路径表达式,否则 jonrsharpe 的注释可能是最直接的解决方案。

    【讨论】:

      【解决方案4】:

      我曾经在我的项目中使用过类似的东西;

      attr = 'detail.infotext'.split('.')
      if len(attr) == 1:
          return getattr(item, attr[0], "")
      else:
          return getattr(getattr(item, attr[0], ""), attr[1], "")
      

      或者,只有一个班轮声明;

          attr = "detail.infotext"
          if hasattr(item, attr.rsplit('.', 1)[0]) and hasattr(getattr(item, attr.rsplit('.', 1)[0]), attr.rsplit('.', 1)[1]):
              pass
      

      【讨论】:

        【解决方案5】:

        老问题,但这是基于this 答案的另一种方法,它为嵌套getattr 提供了一个很好的解决方案...

        import functools
        
        def rhasattr(obj, path):
            try:
                functools.reduce(getattr, path.split("."), obj)
                return True
            except AttributeError:
                return False
        

        【讨论】:

          【解决方案6】:

          我一直在寻找同样的东西,但对上述答案并不满意,因为它们没有深入探讨。我创建了这个帮助函数,我倾向于使用它来解决这个问题。可能有些地方它不起作用或坏了,但到目前为止还不错。

          import copy
          def check_if_obj_contains_nested_attribute_path(obj, nested_attr):
              '''Determine if object has the provided nested path - returns True of False
              
              :param str nested_attr: the nested attribute path e.g. 'status.load_balancer.ingress'
              :param obj: The object that you want to test for the attribute on
              '''
              # divide attribute path string into dot parts
              parts = nested_attr.split('.')
              temp_obj = copy.deepcopy(obj)
              
              for part in parts:
                  if hasattr(temp_obj, part):
                      temp_obj = getattr(temp_obj, part)
                  else:
                      return False
              return True
          

          所以现在我可以像这样使用它:

          result_bool = check_if_obj_contains_nested_attribute_path(obj, 'status.load_balancer.ingress')
          

          我确信周围有人可能会通过意外的类型捕获和更高效的代码、更少的行等来改进这一点……但目前它确实可以完成这项工作。

          【讨论】:

            猜你喜欢
            • 2019-07-26
            • 2012-05-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多