Person

This class uses a convenient decorator, total_ordering, from the functools module. It simplifies the effort involved in specifying all of the possible rich comparison operations. The class need only define an __eq__ method and one or more of __lt__, __le__, __gt__, or __ge__. This class decorator supplies the rest of the methods not already defined.

from functools import total_ordering


@total_ordering
class Person:

    """Person with first and last name."""

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __lt__(self, other):
        last_equal = (self.last_name == other.last_name)
        less_than = (last_equal and self.first_name < other.first_name) or self.last_name < other.last_name
        return less_than

    def __eq__(self, other):
        same_names = (self.last_name == other.last_name) and (self.first_name == other.first_name)
        if same_names:
            return True
        else:
            return False

    def __str__(self):
        full_name = self.first_name + " " + self.last_name
        return full_name

    def __repr__(self):
        representation = self.__class__.__name__ + "(" + repr(self.first_name) + ", " + repr(self.last_name) + ")"
        return representation


if __name__ == "__main__":
    james = Person("James", "Rankin")
    zane = Person("Zane", "Shavers")
    jackie = Person("Jackie", "Taylor")
    ladonna = Person("Ladonna", "Taylor")
    assert sorted([zane, jackie, james, ladonna]) == [james, zane, jackie, ladonna]
    print("Tests passed")
  1. Rely on comparison operation on tuple to compare values in order: “Simple is better than complex.”

  2. Remove variables unnecessarily assigned and then returned immediately: “Beautiful is better than ugly.”

  3. Use string formatting to improve __repr__, relying on line continuation for line wrapping: “Beautiful is better than ugly.” and “Complex is better than complicated.” and “Readability counts.”

  4. Use the string join method to join together the first and last name with a space: PEP 8 and “Simple is better than complex.”

@total_ordering
class Person:

    """Person with first and last name."""

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __lt__(self, other):
        return (self.last_name, self.first_name) < (other.last_name, other.first_name)

    def __eq__(self, other):
        return (self.last_name, self.first_name) == (other.last_name, other.first_name)

    def __str__(self):
        return " ".join((self.first_name, self.last_name))

    def __repr__(self):
        return f"{self.__class__.__name__}({repr(self.first_name)}, {repr(self.last_name)})"

Make a legal_names property returning a tuple which can be used to shorten code: “Simple is better than complex.” and “Readability counts.”

def __lt__(self, other):
    return self.legal_names < other.legal_names

def __eq__(self, other):
    return self.legal_names == other.legal_names

@property
def legal_names(self):
    return (self.last_name, self.first_name)