如何链接可能在Python中返回None的属性查找?

发布于 2021-01-29 16:31:19

我的问题是一个一般的问题,当中间一个可能返回时,如何链接一系列属性查找None,但是由于我在尝试使用Beautiful
Soup时遇到了这个问题,因此我将在这种情况下提出该问题。

Beautiful
Soup解析HTML文档并返回一个对象,该对象可用于访问该文档的结构化内容。例如,如果解析的文档在变量中soup,则可以使用以下命令获取其标题:

title = soup.head.title.string

我的问题是,如果文档没有标题,则soup.head.title返回None,随后的string查找将引发异常。我可以将链分解为:

x = soup.head
x = x.title if x else None
title = x.string if x else None

但是在我看来,这是冗长且难以阅读的。

我可以写:

title = soup.head and soup.head.title and soup.title.head.string

但这是冗长且低效的。

如果可以想到的一种解决方案(我认为是可行的)将是创建一个对象(称为nil),该对象None将为任何属性查找返回。这可以让我写:

title = ((soup.head or nil).title or nil).string

但这很丑。有没有更好的办法?

关注者
0
被浏览
46
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您可能可以使用reduce此功能:

    >>> class Foo(object): pass
    ... 
    >>> a = Foo()
    >>> a.foo = Foo()
    >>> a.foo.bar = Foo()
    >>> a.foo.bar.baz = Foo()
    >>> a.foo.bar.baz.qux = Foo()
    >>> 
    >>> reduce(lambda x,y:getattr(x,y,''),['foo','bar','baz','qux'],a)
    <__main__.Foo object at 0xec2f0>
    >>> reduce(lambda x,y:getattr(x,y,''),['foo','bar','baz','qux','quince'],a)
    ''
    

    在python3.x中,我认为它reduce已移至functools:(


    我想您也可以使用更简单的功能来做到这一点:

    def attr_getter(item,attributes)
        for a in attributes:
            try:
                item = getattr(item,a)
            except AttributeError:
                return None #or whatever on error
        return item
    

    最后,我想 最好的 方法是:

    try:
       title = foo.bar.baz.qux
    except AttributeError:
       title = None
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看