执行此代码:
class Person(object):
def __init__(self, name):
self.name = name
try:
lastBlank = name.rindex(' ')
self.lastName = name[lastBlank+1:]
except:
self.lastName = name
def __lt__(self, other):
if self.lastName == other.lastName:
return self.name < other.name
return self.lastName < other.lastName
def __str__(self):
return self.name
me = Person('Michael Guttag')
him = Person('Barack Hussein Obama')
her = Person('Madonna')
pList = [me, him, her]
pList.sort() #invoke __lt__()
for p in pList:
print p
并输出:
Michael Guttag
Madonna
Barack Hussein Obama
在这本书中,它举例说明了类和运算符重载(或多态性),它说:除了提供编写使用<
的中缀表达式的语法便利外,这种重载还提供了对使用__lt__
定义的任何多态方法的自动访问。内置的方法sort就是这样一种方法。因此,例如,如果pList
是由类型为Person
的元素组成的列表,则调用pList.sort()
将使用类Person
中定义的__lt__
方法对该列表进行排序。
我不明白sort()
是如何产生多态性的(实际上,经过大量研究,多态性的概念我还不清楚),也不知道__lt__
是如何进行排序以给出这样的输出的。我需要一个循序渐进的指导。非常感谢。
丰富的比较方法__lt__
、__le__
、__gt__
、__ge__
和__eq__
实现了各种比较操作。它们都比较两个对象(其中一个是self
)。它们一起可以让你回答诸如"在这两个对象中,如果有一个,哪个更大"之类的问题?有很多排序算法可以让你列出一个对象列表,如果你能在每一对对象上回答这样的问题,你就可以把整个列表按正确的顺序排列。例如,一种更容易理解的方法被称为选择排序——它的工作原理是:
- 比较前两项。取最小的(如果相等,则选择第一个),称之为
s
- 将
s
与您尚未检查的下一个项目进行比较,如果该项目较小,则它现在是s
(否则,s
仍然是旧的s
) - 重复执行步骤2,直到您没有更多未检查的项目为止。这意味着
s
现在是您列表中最小的项目 - 将
s
移到列表的开头,将所有其他内容上移以填补s
所在的"空白" - 考虑列表的其余(即,排除第一项),并在此基础上运行整个过程
- 继续——排除前两个,然后是前三个,以此类推——直到剩下的列表只有一个项目。现在对整个列表进行排序
Python的list.sort
方法运行一种更复杂但更快的算法,称为Timsort。它实现了同样的目的:假设你可以知道任何两个元素是如何相对于彼此排序的,它会为你对整个列表进行排序。
Timsort如何工作的细节并不重要——使用现有方法而不是编写自己的方法的意义在于,你可以相信它确实有效。重要的一点是,文档中没有任何地方可以保证它将使用<
来比较每对元素-最好至少实现__eq__
,这样sort
就可以知道两个Person
是否恰好相等。你可以这样写:
def __eq__(self, other):
return self.name == other.name
一旦你做到了这一点,就有一个名为functools.total_ordering
的内置魔术,它可以为你填充所有剩余的比较方法。你可以这样使用它:
import functools
@functools.total_ordering
class Person:
....