从列表中删除非类型元素的本机Python函数?
我正在使用Python中的Beauty Soup从HTML文件中获取一些数据。在某些情况下,Beautiful Soup返回同时包含从列表中删除非类型元素的本机Python函数?,python,list,nonetype,Python,List,Nonetype,我正在使用Python中的Beauty Soup从HTML文件中获取一些数据。在某些情况下,Beautiful Soup返回同时包含string和NoneType对象的列表。我想过滤掉所有NoneType对象 在Python中,包含NoneType对象的列表是不可编辑的,因此列表理解不是这个选项。具体地说,如果我有一个列表lis包含NoneTypes,并且我尝试执行类似[x代表lis中的x(某些条件/函数)],Python抛出错误TypeError:type'NoneType'的参数不可写 正如
string
和NoneType
对象的列表。我想过滤掉所有NoneType
对象
在Python中,包含NoneType
对象的列表是不可编辑的,因此列表理解不是这个选项。具体地说,如果我有一个列表lis
包含NoneTypes
,并且我尝试执行类似[x代表lis中的x(某些条件/函数)]
,Python抛出错误TypeError:type'NoneType'的参数不可写
正如我们在中所看到的,在用户定义的函数中实现此功能非常简单。以下是我的感受:
def filterNoneType(lis):
lis2 = []
for l in links: #filter out NoneType
if type(l) == str:
lis2.append(l)
return lis2
但是,如果存在内置Python函数,我希望使用它。如果可能的话,我总是喜欢简化我的代码Python是否有一个内置函数可以从列表中删除NoneType
对象?您可以使用列表理解:
clean = [x for x in lis if x != None]
lis = [i for i in lis if i is not None]
正如注释中所指出的,您也可以使用is not
,即使它基本上编译为相同的字节码:
clean = [x for x in lis if x is not None]
您还可以使用过滤器
(注意:这也会过滤空字符串,如果您想对过滤内容进行更多控制,可以传递函数,而不是无
):
如果您想要更高效的循环,总会有一种方法,但这些基本方法应该适用于大多数日常情况。您可以使用列表理解轻松地从列表中删除所有NoneType
对象:
clean = [x for x in lis if x != None]
lis = [i for i in lis if i is not None]
列出理解,如建议的其他答案,或为了完整起见:
clean = filter(lambda x: x is not None, lis)
如果列表很大,则迭代器方法更优越:
from itertools import ifilter
clean = ifilter(lambda x: x is not None, lis)
我认为最干净的方法是:
#lis = some list with NoneType's
filter(None, lis)
对于那些从谷歌来到这里的人-不要使用这个!
UPD 2021:
在编写这个答案时,所建议的实现在语言语义方面是绝对有效的,但显然是一种黑客行为。从那时起,情况发生了变化,从Python 3.9开始,明确禁止在布尔上下文中对NotImplemented
进行评估。下面是Python文档的摘录:
不推荐在布尔上下文中实现。虽然它当前的计算结果为true,但它将发出DeprecationWarning。它将在Python的未来版本中引发TypeError
为了历史的缘故,我将保留这个答案,但请注意,即使是在这个时候,这也有点骇人听闻。根据您的要求,坚持使用建议的列表理解解决方案或过滤器+lambda
原始答案:
截至2019年初,Python没有用于过滤None值的内置函数,这避免了删除零、空字符串等常见陷阱
在Python3中,您可以使用。\uuuu ne\uuuu
dunder方法(如果愿意,也可以使用“魔术方法”)实现此功能:
这就是它的工作原理:
None.\uune\uu(None)
-->错误
None.\uu_______(任何东西)
-->未实现
NotImplemented
有效验证为True
,例如:
>>> bool(None.__ne__('Something'))
True
根据PEP 8,您应该使用不是而不是=代码>与单例进行比较时。filter()首先使用函数argument@ThorstenKranz如果第一个参数为None
,则它会过滤掉所有False
类条目(None
、空字符串、零等).@ThorstenKranzfilter
with None将从列表中删除所有None项,并且比传递lambda函数效率更高,后者速度较慢。@CharlesMenguy唯一的问题是它还将删除空字符串(这实际上可能不是问题,因为OP将迭代这些内容,并且在任何情况下都可能忽略它们)。您错误地认为包含None
的列表是不可迭代的。您可能(意外地)尝试迭代None
本身:[x代表x代表None]
。这是错误的,因为它还将删除0
、False
和'
元素。很公平。您可以使用过滤器(lambda x:x!=无,lis)
then.@Abs,filter
是从dicts中删除具有None
值的键值对的合适方法吗?filter
实际上不修改任何内容-它创建一个新的过滤dict。要真正删除键值对,您需要使用del
。例如:del(somedict[key\u to\u delete])
将从dict中删除一个键。这更迂腐正确:lambda x:x不是None
供未来读者参考的一般说明:在Python3中,filter
已经返回了一个迭代器,因此sceond方法是不必要的。它只与Python 2相关。如果您确实想要使用Python 3的列表,只需执行list(filter(…)
网络上唯一优雅的答案。@tejasvi88在filter中使用dunder方法一点也不优雅。这是一个难看的黑客行为。在这种情况下,列表理解更受欢迎。