我正在寻找一种更优雅的方式来声明一个变量值,其中函数可以返回None
并且在函数调用之后存在链接方法。
在下面的示例中,我使用BeautifulSoup传递HTML文档,如果找不到我要查找的元素,则初始函数调用返回None
。然后链接的方法会破坏代码,因为.string
不是None
对象的方法。
哪一切都有意义,但我想知道是否有更简洁的方法来编写这些不会在None
值上破坏的变量声明。
# I want to do something like this but it throws error if soup.find returns
# none because .string is not a method of None.
title = soup.find("h1", "article-title").string or "none"
# This works but is both ugly and inefficient
title = "none" if soup.find("h1", "article-title") is None else soup.find("h1", "article-title").string
# So instead I'm using this which feels clunky as well
title = soup.find("h1", "article-title")
title = "none" if title is None else title.string
有更好的方法吗?
答案 0 :(得分:4)
我喜欢Shashank的回答,但这对你也有用:
class placeholder:
string = "none"
title = (soup.find("h1", "article-title") or placeholder).string
答案 1 :(得分:2)
美丽汤的这种行为确实让我很烦。这是我的解决方案:http://soupy.readthedocs.org/en/latest/
这可以平滑BeautifulSoup中的许多边缘情况,允许您编写像
这样的查询dom.find('h1').find('h2').find('a')['href'].orelse('not found').val()
如果存在,则返回您要查找的内容,否则返回“未找到”。
汤的一般策略是将您关心的数据包装在瘦包装类中。这种包装器的一个简单示例:
class Scalar(object):
def __init__(self, val):
self._val = val
def __getattr__(self, key):
return Scalar(getattr(self._val, key, None))
def __call__(self, *args, **kwargs):
return Scalar(self._val(*args, **kwargs))
def __str__(self):
return 'Scalar(%s)' % self._val
s = Scalar('hi there')
s.upper() # Scalar('HI THERE')
s.a.b.c.d # Scalar(None)
如果你想对它感兴趣,那么让你安全链接东西的数学属性是 closure (即方法返回相同类型的实例)。很多BeautifulSoup方法都没有这个属性,这就是什么样的地址。
答案 2 :(得分:1)
如果在给定对象中找不到所需的属性,您可以使用getattr
内置函数提供默认值:
title = getattr(soup.find("h1", "article-title"), "string", "none")
或者,您可以使用try statement
:
try:
title = soup.find("h1", "article-title").string
except AttributeError:
title = "none"
在我看来,第一种方法更优雅。