从列表中删除 NoneType 元素的本机 Python 函数?
Posted
技术标签:
【中文标题】从列表中删除 NoneType 元素的本机 Python 函数?【英文标题】:Native Python function to remove NoneType elements from list? 【发布时间】:2012-12-23 03:48:36 【问题描述】:我在 Python 中使用 Beautiful Soup 从 html 文件中抓取一些数据。在某些情况下,Beautiful Soup 返回包含 string
和 NoneType
对象的列表。我想过滤掉所有的 NoneType
对象。
在 Python 中,包含 NoneType
对象的列表是不可迭代的,因此列表推导式不是一个选项。具体来说,如果我有一个包含NoneTypes
的列表lis
,并且我尝试执行[x for x in lis (some condition/function)]
之类的操作,Python 会抛出错误TypeError: argument of type 'NoneType' is not iterable
。
正如我们在other posts 中看到的,在用户定义的函数中实现此功能非常简单。这是我的口味:
def filterNoneType(lis):
lis2 = []
for l in links: #filter out NoneType
if type(l) == str:
lis2.append(l)
return lis2
但是,如果存在的话,我很乐意为此使用内置的 Python 函数。我总是喜欢尽可能简化我的代码。 Python 是否有可以从列表中删除 NoneType
对象的内置函数?
【问题讨论】:
你错了,包含None
的列表是不可迭代的。您可能(意外地)尝试迭代 None
本身:[x for x in None]
。
【参考方案1】:
我认为最干净的方法是:
#lis = some list with NoneType's
filter(None, lis)
【讨论】:
这是错误的,因为它还会删除0
、False
和''
元素。
很公平。然后你可以使用filter(lambda x: x!=None, lis)
。
@Abs,filter
是从字典中删除带有None
值的键值对的适当方式吗?
filter
实际上并没有修改任何内容 - 它创建了一个新的过滤字典。要实际删除键值对,您需要使用del
。例如:del(somedict[key_to_delete])
将从字典中删除一个键。
这更迂腐正确:lambda x: x is not None
【参考方案2】:
您可以使用列表推导来做到这一点:
clean = [x for x in lis if x != None]
正如 cmets 中所指出的,您也可以使用 is not
,即使它本质上编译为相同的字节码:
clean = [x for x in lis if x is not None]
你也可以使用filter
(注意:这也会过滤空字符串,如果你想更好地控制你过滤的内容,你可以传递一个函数而不是None
):
clean = filter(None, lis)
如果您想要更有效的循环,总是有itertools 方法,但这些基本方法应该适用于大多数日常情况。
【讨论】:
根据 PEP 8,与单例比较时,您应该使用is not
而不是 !=
。
filter() 将函数作为第一个参数
@ThorstenKranz 如果第一个参数是None
,它会过滤掉所有类似False
的条目(None
、空字符串、零等)。
@ThorstenKranz filter
with None 将从列表中删除所有 None 条目,并且比传递更慢的 lambda 函数更有效。
@CharlesMenguy 唯一的问题是它还会删除空字符串(这实际上可能不是问题,因为 OP 将遍历这些字符串并且在任何情况下都可能忽略它们)。跨度>
【参考方案3】:
列出理解,作为其他答案,或者为了完整起见:
clean = filter(lambda x: x is not None, lis)
如果列表很大,迭代器方法会更好:
from itertools import ifilter
clean = ifilter(lambda x: x is not None, lis)
【讨论】:
给未来读者的一般注意事项:在 Python3 中,filter
已经 返回一个迭代器,因此不需要第二种方法。它仅与 Python 2 相关。如果您真的想要使用 Python 3 的列表,只需执行 list(filter(...))
【参考方案4】:
对于那些从 Google 来到这里的人 - 不要使用这个!
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
exeption 实际上是True
,例如:
>>> bool(None.__ne__('Something'))
True
【讨论】:
网络上唯一优雅的答案。 @tejasvi88 在过滤器中使用 dunder 方法绝非优雅。这是一个丑陋的黑客。在这种情况下,列表推导更受欢迎。【参考方案5】:您可以使用列表推导轻松地从列表中删除所有 NoneType
对象:
lis = [i for i in lis if i is not None]
【讨论】:
以上是关于从列表中删除 NoneType 元素的本机 Python 函数?的主要内容,如果未能解决你的问题,请参考以下文章