【问题标题】:Checking for None when accessing nested attributes访问嵌套属性时检查无
【发布时间】:2016-10-25 07:33:32
【问题描述】:

我目前正在实现一个 ORM,它存储在 XSD 中定义的数据,该 XSD 由PyXB 生成的 DOM 处理。 许多各自的元素包含子元素等等,每个元素都有一个minOccurs=0,因此在DOM中可能解析为None。 因此,当访问一些包含可选元素的元素层次结构时,我现在面临是否使用的问题:

with suppress(AttributeError):
    wanted_subelement = root.subelement.sub_subelement.wanted_subelement

或者说

if root.subelement is not None:
    if root.subelement.sub_subelement is not None:
        wanted_subelement = root.subelement.sub_subelement.wanted_subelement

虽然两种样式都可以正常工作,但哪种更可取? (顺便说一句,我不是荷兰人。)

【问题讨论】:

    标签: python attributes


    【解决方案1】:

    这也有效:

    if root.subelement and root.subelement.sub_subelement:
        wanted_subelement = root.subelement.sub_subelement.wanted_subelement
    

    if 语句将 None 评估为 False 并将从左到右检查。因此,如果第一个元素的计算结果为 false,它将不会尝试访问第二个元素。

    【讨论】:

    • 是的,你是对的。但这样一来,表达式的长度很容易超过 80 个字符。
    【解决方案2】:

    如果您有很多这样的查找要执行,最好将其包装在更通用的查找函数中:

    # use a sentinel object distinct from None 
    # in case None is a valid value for an attribute
    notfound = object()
    
    # resolve a python attribute path
    # - mostly, a `getattr` that supports
    #   arbitrary sub-attributes lookups    
    def resolve(element, path):
        parts = path.split(".")
        while parts:
           next, parts = parts[0], parts[1:]
           element = getattr(element, next, notfound)
           if element is notfound:
               break
        return element
    
    # just to test the whole thing    
    class Element(object):
       def __init__(self, name, **attribs):
           self.name = name
           for k, v in attribs.items():
               setattr(self, k, v)
    
    e  = Element(
        "top",
        sub1=Element("sub1"),
        nested1=Element(
            "nested1", 
            nested2=Element(
                "nested2", 
                 nested3=Element("nested3")
                 )
            )
        )
    
    
    tests = [
        "notthere",
        "does.not.exists",
        "sub1",
        "sub1.sub2",
        "nested1",
        "nested1.nested2",
        "nested1.nested2.nested3"
        ]
    
    for path in tests:
        sub = resolve(e, path)
        if sub is notfound:
            print "%s : not found" % path
        else:
            print "%s : %s" % (path, sub.name)
    

    【讨论】:

    • 我实际上确实有很多这些访问检查要执行。但是,通过路径的字符串化版本访问属性可能会降低我的代码的可读性和错误倾向,并且会使 PyXB DOM 模型变得荒谬。
    • @RichardNeumann 就我而言,我发现“字符串化路径”分辨率比if elt.attr and elt.attr.subattr and elt.attr.subattr.subsubattr 等的长行更具可读性,但这可能是主观的。 Wrt/ 荒谬,我会说不支持路径表达式查找的 DOM 模型 荒谬的,但这里又是 YMMV ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2015-01-01
    相关资源
    最近更新 更多