从列表中删除非类型元素的本机Python函数?

从列表中删除非类型元素的本机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'的参数不可写 正如

我正在使用Python中的Beauty Soup从HTML文件中获取一些数据。在某些情况下,Beautiful Soup返回同时包含
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
、空字符串、零等).@ThorstenKranz
filter
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方法一点也不优雅。这是一个难看的黑客行为。在这种情况下,列表理解更受欢迎。