在Python中有排序()的神奇方法吗?

时间:2018-02-19 14:24:42

标签: python oop magic-methods

我知道python中有一些魔术方法可以被类覆盖,以控制某些内置函数处理这些类成员的方式。例如,len()str()的行为可以通过魔术方法__len__()__str__()覆盖:

class EmptySet(object):
    def __len__(self):
        return 0

    def __str__(self):
        return '[]'

>>> e = EmptySet()
>>> str(e)
[]

>>> len(e)
0

还有__cmp__()__ge__()__le__()等方法来控制如何比较这些对象以及如何按list.sort()排序它们的列表。我的问题不是关于自定义列表中对象的排序,而是关于对对象本身进行排序。假设该集合不为空,我想使用sorted()对其进行排序:

class SetOfTwo(object):
    def __init__(self, a , b):
        el_0 = a
        el_1 = b

    def __len__(self):
        return 2

    def __str__(self):
        return '[{}, {}]'.format(el_0, el_1)

我是否可以实现一种神奇的方法让sorted()翻转元素,如果它们不正常?我正在描绘以下行为:

>>> s = SetOfTwo(2, 1)
>>> str(s)
[2, 1]

>>> t = sorted(s)
>>> str(t)
[1, 2]

>>> type(t)
>>> SetOfTwo

3 个答案:

答案 0 :(得分:2)

您一定要阅读the official documentation如何模拟容器类型。基本上一个应该作为容器(list,dict等)工作的类需要实现设置或获取成员__getitem__()__setitem__()并迭代项__iter__()并获取数字的方法项目 - 方法__len__()这是最低限度。但您也可以添加删除项目和其他操作的功能。

sorted()内置函数的行为是迭代容器的元素,并使用您提到的__cmp__(), __ge__(), __le__()方法来比较它们,这些方法应该为项目而不是容器定义,如您所知。然后创建一个新的list实例,其中的项目已排序,并返回此新实例。您可以将它传递给自定义容器的构造函数,或者您可以使用自定义函数来移动sorted(),该函数将返回所需的类实例。

答案 1 :(得分:1)

正如有些人在评论中所说,集合是无序的,但我认为你的问题不是关于集合的。

Python使用您提到的数据模型方法 ge le cmp 来确定类在排序()时的行为方式呼吁它。您可以看到我在这里尝试调用它,但Python对象并要求我实现<。

>>> class a(object):
...   pass
...
>>> b = a()
>>> c = a()
>>> d = [b, c]
>>> sorted(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'a' and 'a'

希望这会有所帮助。正如其他人所说的那样,在collections.abc中继承一些东西是个好主意。我在有效的python 中阅读了第28项,其中讨论了这个以获得一个好主意。

答案 2 :(得分:1)

len()str()是将对象作为参数并返回整数(resp。字符串)的函数。该对象可以通过__len__()__str__()魔术方法个性化len计算方式或生成字符串。

类似地,sorted()是一个函数,它接受一个列表(或任何可迭代的)对象并返回一个已排序对象的列表。这些对象可以通过__lt__()魔术方法个性化它们的比较方式。

当我们将`sorted(my_list)视为&#34;对列表排序&#34;而不是&#34;排序列表的元素时出现了一些混淆&# 34。

您不想对对象进行排序(即制作有序的对象列表),但只对其内部表示中的某些数据进行排序。因此,您需要在对象上使用实例方法来更新该内部表示。您可以根据需要对其进行命名,.sort()如果您愿意,但您必须在一个对象上调用它,并且它不会参与比较对象。