Pythonic比较函数

Mik*_*eck 1 python comparison metaprogramming

为简单起见,假设我在Python中有一个Person类.该类包含firstname,lastname和dob的字段.

class Person:
  def __init__(self, firstname, lastname, dob):
    self.firstname = firstname;
    self.lastname = lastname;
    self.dob = dob;
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我想按姓氏排序人员列表,然后是firstname,后跟dob.在其他情况下,我想先用dob排序,然后用lastname排序,最后用firstname排序.有时我只想按名字排序.

创建第一个比较函数的天真解决方案是这样的:

def comparepeople(person1, person2):
  if cmp(person1.lastname, person2.lastname) == 0:
    if cmp(person1.firstname, person2.firstname) == 0:
      return cmp(person1.dob, person2.dob);
    return cmp(person1.firstname, person2.firstname);
  return cmp(person1.lastname, person2.lastname);
Run Code Online (Sandbox Code Playgroud)

看起来应该有一种简单的方法来定义这样的比较函数,使用元编程方法,我需要做的就是按优先顺序提供字段名称,而不是编写这些非常冗长,丑陋的比较方法.但我最近才开始玩Python,并没有找到类似我所描述的内容.

所以问题是,对于具有多个可比构成成员的类,编写比较函数的最Pythonic方法是什么?

Mar*_*wis 10

如果你真的想要一个比较功能,你可以使用

def comparepeople(p1, p2):
    o1 = p1.lastname, p1.firstname, p1.dob
    o2 = p2.lastname, p2.firstname, p2.dob
    return cmp(o1,o2)
Run Code Online (Sandbox Code Playgroud)

这依赖于元组比较.如果要对列表进行排序,则不应编写比较函数,而是一个关键函数:

l.sort(key=lambda p:(p.lastname, p.firstname, p.dob))
Run Code Online (Sandbox Code Playgroud)

这样做的优点是:a)更短,b)更快,因为每个键只计算一次(而不是在排序期间在比较函数中创建的吨元组).