Вот один из способов (возможно, не самый быстрый):
def compare_people_flexibly(p1, p2, attrs):
"""Compare `p1` and `p2` based on the attributes in `attrs`."""
v1 = [getattr(p1, a) for a in attrs]
v2 = [getattr(p2, a) for a in attrs]
return cmp(v1, v2)
def compare_people_firstname(p1, p2):
return compare_people_flexibly(p1, p2, ['firstname', 'lastname', 'dob'])
def compare_people_lastname(p1, p2):
return compare_people_flexibly(p1, p2, ['lastname', 'firstname', 'dob'])
Это работает, потому что getattr может использоваться для получения атрибутов, названных строкой, и потому что Python сравнивает списки, как вы ожидаете, на основе сравнения первых неравных элементов.
Другой способ:
def compare_people_flexibly(p1, p2, attrs):
"""Compare `p1` and `p2` based on the attributes in `attrs`."""
for a in attrs:
c = cmp(getattr(p1, a), getattr(p2, a))
if c:
return c
return 0
Это имеет то преимущество, что не создает два полных списка атрибутов, поэтому может быть быстрее, если списки атрибутов длинные или если много сравнений завершено для первого атрибута.
Наконец, как отмечает Мартин, вам может понадобиться ключевая функция, а не функция сравнения:
def flexible_person_key(attrs):
def key(p):
return [getattr(p, a) for a in attrs]
return key
l.sort(key=flexible_person_key('firstname', 'lastname', 'dob'))