我知道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
答案 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()
如果您愿意,但您必须在一个对象上调用它,并且它不会参与比较对象。