を使用してオブジェクトのリストを並べ替えようとしています
my_list.sort(key=operator.attrgetter(attr_name))
ただし、リストアイテムのいずれかに_attr = None
_ではなく_attr = 'whatever'
_がある場合、
次に、TypeError: unorderable types: NoneType() < str()
を取得します
Py2では問題ありませんでした。 Py3でこれを処理するにはどうすればよいですか?
順序比較演算子は、Python 3で説明されているように、タイプについてより厳密です ここ :
順序比較演算子(<、<=、> =、>)は、オペランドに意味のある自然順序がない場合に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)
一般的な解決策として、他のどのオブジェクトよりも比較が少ないオブジェクトを定義できます。
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)
ここで提案されたソリューションは機能しますが、これはさらに短縮できます。
mylist.sort(key=lambda x: x or 0)
基本的に、Noneは値0であるかのように扱うことができます。
例えば。:
>>> mylist = [3, 1, None, None, 2, 0]
>>> mylist.sort(key=lambda x: x or 0)
>>> mylist
[None, None, 0, 1, 2, 3]
None
以外にも文字列に匹敵しないものがあるので(初心者向けのintとlists)、一般的な問題に対するより堅牢な解決策を次に示します。
_my_list.sort(key=lambda x: x if isinstance(x, str) else "")
_
これにより、文字列とstr
から派生したすべてのタイプを比較し、他のすべてを空の文字列でビンに入れることができます。または、必要に応じて、別のデフォルトのデフォルトキーに置き換えます。 _"ZZZZ"
_またはchr(sys.maxunicode)
を使用して、このような要素を最後にソートします。