更"pythonic"的"check for None and deal with it"方法



我有一个dict list,键['name','content','summary',...]。所有值都是字符串。但是有些价值观是None.我需要删除contentsummary和其他一些键中的所有新行。所以,我这样做:

...
...
for item in item_list:
    name = item['name']
    content = item['content']
    if content is not None: content = content.replace('n','')
    summary = item['summary']
    if summary is not None: summary = summary.replace('n','')
    ...
    ...
...
...

我有点觉得if x is not None: x = x.replace('n','')成语不是那么聪明或干净。有没有更"pythonic"或更好的方法?

谢谢。

代码对你来说感觉很笨拙,但部分原因是因为你在重复自己。这样更好:

def remove_newlines(text):
    if text is not None:
        return text.replace('n', '')
for item in item_list:
    name = item['name']
    content = remove_newlines(item['content'])
    summary = remove_newlines(item['summary'])

如果你打算使用哨兵值(None),那么你将承担检查它们的负担。

你的问题有很多不同的答案,但他们似乎忽略了这一点:当缺少条目编码相同的信息时,不要在字典中使用哨兵值。

例如:

bibliography = [
    { 'name': 'bdhar', 'summary': 'questioner' },
    { 'name': 'msw', 'content': 'an answer' },
]

然后你可以

for article in bibliography:
    for key in article:
        ...

然后你的循环很好地忽略了给定文章中包含哪些键(如果有的话)。

在阅读您的评论时,您声称您是从其他地方获得的字典。所以先清理垃圾值。有一个清理步骤比通过你的代码传达他们的误解要清楚得多

Python 有一个三元运算符,所以一种选择是以更自然的词序执行此操作:

content = content.replace('n', '') if content is not None else None

请注意,如果 ""None 在您的情况下是等效的(似乎是这样),您可以将其缩短为仅 if content ,因为非空字符串的计算结果为 True

content = content.replace('n', '') if content else None

这也遵循了Python习语"显式优于隐式"。这向遵循代码的人表明,该值可以非常清楚地None

值得注意的是,如果您多次重复此操作,则可能值得将其封装为函数。

Python中的另一个成语是请求宽恕,而不是许可。因此,您可以简单地使用tryexcept随后的AttributeError,但是,在这种情况下,这变得更加冗长,因此可能不值得,尤其是因为检查成本如此之小。

try:
    content = content.replace('n', '')
except AttributeError:
    content = None
    #pass #Also an option, but as mentioned above, explicit is generally clearer than implicit.

一种可能性是使用空字符串而不是 None。 这不是一个完全通用的解决方案,但在许多情况下,如果你的数据都是单一类型,除了 None 之外,还会有一个合理的"null"值(空字符串、空列表、零等)。 在这种情况下,看起来您可以使用空字符串。

空字符串在 Python 中的计算结果为 False,因此 Pythonic 的方式是 if content:

In [2]: bool("")
Out[2]: False
In [3]: bool("hello")
Out[3]: True

旁注,但你可以让你的代码更清晰一点:

name, content = item["name"], item["content"]

和:

content = content.replace('n','') if content else None

你也可以考虑将一些if子句抽象到一个单独的函数中:

def remove_newlines(mystr):
    if mystr:
        mystr = mystr.replace('n')
    return mystr

(编辑以删除带有字典等的过于复杂的解决方案)

尝试:

if content: content = content.replace('n','')

--

if content将(几乎1)始终True,只要 content 包含除 0、False 或 None 之外的任何内容。


1正如 Lattyware 在评论中正确指出的那样,这并不完全正确。还有其他一些内容将在 if 语句中计算False,例如,空列表。请参阅下面评论中提供的链接。

我认为"pythonic"的事情是在if语句中使用None将计算为False的事实。所以你可以说:

if content: content = content.replace('n','')

最新更新