Ale*_*Vhr 19 python python-2to3 python-3.x
我正在尝试使用排序对象列表
my_list.sort(key=operator.attrgetter(attr_name))
但如果有任何列表项attr = None而不是attr = 'whatever',
然后我得到了 TypeError: unorderable types: NoneType() < str()
在Py2中,这不是问题.我如何在Py3中处理这个?
aug*_*rar 25
对于一般解决方案,您可以定义一个比任何其他对象更少的对象:
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()
Run Code Online (Sandbox Code Playgroud)
然后使用排序键替换列表中的Min任何None值
mylist.sort(key=lambda x: Min if x is None else x)
Run Code Online (Sandbox Code Playgroud)
jsa*_*nen 22
排序比较运算符约在Python 3种严格,如描述在这里:
当操作数没有有意义的自然顺序时,排序比较运算符(<,<=,> =,>)会引发TypeError异常.
Python 2 None在任何字符串(甚至空字符串)之前排序:
>>> None < None
False
>>> None < "abc"
True
>>> None < ""
True
Run Code Online (Sandbox Code Playgroud)
在Python 3中,任何排序NoneType实例的尝试都会导致异常:
>>> None < "abc"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < str()
Run Code Online (Sandbox Code Playgroud)
我能想到的最快的解决方案是将None实例显式映射到可订购的东西,如"":
my_list_sortable = [(x or "") for x in my_list]
Run Code Online (Sandbox Code Playgroud)
如果要在保持数据完整性的同时对数据进行排序,只需提供sort自定义key方法:
def nonesorter(a):
if not a:
return ""
return a
my_list.sort(key=nonesorter)
Run Code Online (Sandbox Code Playgroud)
此处提出的解决方案有效,但是可以进一步缩短:
mylist.sort(key=lambda x: x or 0)
Run Code Online (Sandbox Code Playgroud)
本质上,我们可以将None的值视为0。
例如:
>>> mylist = [3, 1, None, None, 2, 0]
>>> mylist.sort(key=lambda x: x or 0)
>>> mylist
[None, None, 0, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
处理None独立于要排序的类型的通用解决方案:
my_list.sort(key=lambda x: (x is not None, x))
Run Code Online (Sandbox Code Playgroud)
把None价值观放在第一位。
请注意:将值my_list.sort(key=lambda x: (x is None, x))放在最后。None