我正在尝试使用
对对象列表进行排序 my_list.sort(key=operator.attrgetter(attr_name))
但如果任何列表项都有attr = None
而不是attr = 'whatever'
,
然后我得到TypeError: unorderable types: NoneType() < str()
在Py2中,这不是问题。我如何在Py3中处理这个?
答案 0 :(得分:23)
对于一般解决方案,您可以定义一个比任何其他对象更少的对象:
from functools import total_ordering
@total_ordering
class MinType(object):
def __le__(self, other):
return True
def __eq__(self, other):
return (self is other)
Min = MinType()
然后使用排序键将Min
替换为列表中的任何None
值
mylist.sort(key=lambda x: Min if x is None else x)
答案 1 :(得分:20)
排序比较运算符对Python 3中的类型更为严格,如here所述:
排序比较运算符(&lt;,&lt; =,&gt; =,&gt;)引发TypeError 操作数没有有意义的自然顺序时的异常。
Python 2在任何字符串(甚至是空字符串)之前排序None
:
>>> None < None
False
>>> None < "abc"
True
>>> None < ""
True
在Python 3中,任何排序NoneType
实例的尝试都会导致异常:
>>> None < "abc"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < str()
我能想到的最快的解决方法是明确将None
个实例映射到像""
这样的可订购项:
my_list_sortable = [(x or "") for x in my_list]
如果您想对数据进行排序,同时保持数据完好无损,只需提供sort
自定义key
方法:
def nonesorter(a):
if not a:
return ""
return a
my_list.sort(key=nonesorter)
答案 2 :(得分:3)
由于None
除了my_list.sort(key=lambda x: x if isinstance(x, str) else "")
之外还有其他东西不能与字符串(整数和列表,对于初学者)相比,这里是一个更稳健的解决方案:
str
这将允许字符串和从"ZZZZ"
派生的任何类型作为它们自己进行比较,并将其他所有内容与空字符串进行比较。或者,如果您愿意,可以替换其他默认默认密钥,例如chr(sys.maxunicode)
或{{1}}使这些元素在最后排序。
答案 3 :(得分:3)
这里提出的解决方案有效,但可以进一步缩短:
mylist.sort(key=lambda x: x or '')