32

我在 Python 中使用 Beautiful Soup 从 HTML 文件中抓取一些数据。在某些情况下,Beautiful Soup 返回包含stringNoneType对象的列表。我想过滤掉所有的NoneType对象。

在 Python 中,包含NoneType对象的列表是不可迭代的,因此列表推导不是一个选项。具体来说,如果我有一个lis包含的列表NoneTypes,并且我尝试执行类似的操作[x for x in lis (some condition/function)],Python 会抛出错误TypeError: argument of type 'NoneType' is not iterable

正如我们在其他帖子中看到的,在用户定义的函数中实现此功能很简单。这是我的味道:

def filterNoneType(lis):
    lis2 = []
    for l in links: #filter out NoneType
        if type(l) == str:
            lis2.append(l)
    return lis2

但是,如果存在,我很乐意为此使用内置的 Python 函数。我总是喜欢尽可能简化我的代码。Python 是否具有可以从列表中删除对象的内置函数?NoneType

4

5 回答 5

65

我认为最干净的方法是:

#lis = some list with NoneType's
filter(None, lis)
于 2013-01-09T07:40:54.533 回答
25

您可以使用列表推导来做到这一点:

clean = [x for x in lis if x != None]

正如评论中所指出的,您也可以使用is not,即使它本质上编译为相同的字节码:

clean = [x for x in lis if x is not None]

你也可以使用filter(注意:这也会过滤空字符串,如果你想更多地控制你过滤的内容,你可以传递一个函数而不是None):

clean = filter(None, lis)

如果您想要更有效的循环,总是有itertools方法,但这些基本方法应该适用于大多数日常情况。

于 2013-01-09T06:28:30.973 回答
7

列表理解,正如其他答案所建议的那样,或者为了完整起见:

clean = filter(lambda x: x is not None, lis)

如果列表很大,迭代器方法更好:

from itertools import ifilter
clean = ifilter(lambda x: x is not None, lis)
于 2013-01-09T06:31:11.337 回答
7

对于那些从谷歌来到这里的人——不要使用这个!

UPD 2021:
编写此答案时,提议的实现在语言语义方面绝对有效,但显然是一个hack。从那时起事情发生了变化,从 Python 3.9 开始NotImplemented,布尔上下文中的评估被明确禁止。这是 Python 文档的摘录:

不推荐在布尔上下文中评估 NotImplemented。虽然它当前评估为 true,但它会发出 DeprecationWarning。它将在 Python 的未来版本中引发 TypeError。

为了历史起见,我会保留这个答案,但请注意,即使在当时,这也有点不合时宜。根据您的要求坚持建议的列表理解解决方案或filter+ 。lambda

原始答案:
截至 2019 年初,Python 没有用于过滤 None 值的内置函数,从而避免了删除零、空字符串等常见错误。

在 Python3 中,您可以使用 .__ne__dunder 方法(如果您愿意,也可以使用“魔术方法”)来实现它:

>>> list1 = [0, 'foo', '', 512, None, 0, 'bar']
>>> list(filter(None.__ne__, list1))
[0, 'foo', '', 512, 0, 'bar']

这是它的工作原理:

  • None.__ne__(None)--> 错误

  • None.__ne__(anything)--> 未实现

NotImplemented有效的例外是True,例如:

>>> bool(None.__ne__('Something'))
True
于 2019-01-18T19:09:36.120 回答
2

NoneType您可以使用列表推导轻松地从列表中删除所有对象:

lis = [i for i in lis if i is not None]
于 2013-01-09T06:28:37.280 回答