基于多个属性对类进行排序

时间:2021-03-31 00:01:20

标签: python comparison operators rich

我目前使用的是 Python 3.9.1 或 3.8(取决于我使用的设备)

我在 Medium.com 上阅读了一篇关于使用运算符模块使用字典中的多个键进行排序的文章。我已经实现了一个使用内置富比较运算符的类,我想知道是否有办法从类中获取相同的功能。我想出了(一种方法)获得单属性功能:

class Person:
"""    The Person class functions as it own representation of a person and base class.

       In this video game simulation it functions as the starting point for the Employee
       and Customer class but can be adapted to another other operation that deals
       with people.

       Attributes
       ----------
       _first_name : str
           The first name of the person
       _middle_name : str
           The middle name of the person
       _last_name : str
           The last name of the person
       _dob : datetime.datetime
           The property for this will accept a string formatted as "mm.dd.yyyy" and convert it to
           a datetime.datetime as well as accepting a datetime.datetime directly
       _age : int
           This is calculated and assigned a value the date of birth is assigned or changed
       _sex : int
           For this class 0 is male and 1 is female will build conversion from string representation
       _married : bool
           Is the person married?
       _hair_color : str
           Really kind of torn here and would like to pick a color as an RGBA value but for this simulation
           sticking with text
       _eye_color: str
           Same as hair_color
       _weight : float
           The weight in pounds
       _height : float
           The height in inches

       Methods
       -------

"""

# noinspection SpellCheckingInspection
def __init__(self,
             fname: str,
             mname: str,
             lname: str,
             dob,
             sex,
             married,
             hair_color,
             eye_color,
             weight,
             height,
             sort_by):
    self._first_name = fname
    self._middle_name = mname
    self._last_name = lname
    self._dob = None
    self._age = 0
    self._sex = sex
    self._married = married
    self._hair_color = hair_color
    self._eye_color = eye_color
    self._weight = weight
    self._height = height
    self.dob = dob
    self._sort_by = sort_by
    self.selection = {
        'lastname': self._last_name,
        'middlename': self._middle_name,
        'firstname': self._first_name,
        'dateofbirth': self._dob,
        'age': self._age,
        'height': self._height,
        'weight': self._weight
    }

@property
def name(self):
    return self._first_name + ' ' + self._last_name

@property
def first_name(self):
    return self._first_name

# noinspection SpellCheckingInspection
@first_name.setter
def first_name(self, fname):
    self._first_name = fname

@property
def middle_name(self):
    return self._middle_name

# noinspection SpellCheckingInspection
@middle_name.setter
def middle_name(self, mname):
    self._middle_name = mname

@property
def last_name(self):
    return self._last_name

# noinspection SpellCheckingInspection
@last_name.setter
def last_name(self, lname):
    self._last_name = lname

@property
def dob(self):
    return self._dob

@dob.setter
def dob(self, birth_date):
    if isinstance(birth_date, dt.datetime):
        self._dob = birth_date
        self.set_age(birth_date)
    elif isinstance(birth_date, str):
        date = re.compile(r'(\d\d).(\d\d).(\d\d\d\d)')
        date_result = date.findall(birth_date)

        try:
            date_tuple = date_result[0]
        except IndexError as e:
            date_tuple = ()
            print(e)

        if len(date_tuple) == 3:
            month, day, year = date_tuple
            self.dob = dt.datetime(int(year), int(month), int(day))
        else:
            raise ValueError('Date string value not valid must be in the '
                             'form MM_DD_YYYY where the underscore _ is any'
                             ' character')

    else:
        raise TypeError(
            f'Expected datetime.datetime or string but got {type(birth_date)}'
        )

def set_age(self, date_of_birth):
    days_delta = dt.datetime.now() - date_of_birth
    self._age = int(days_delta.days / 365)

@property
def age(self):
    return self._age

@property
def sex(self):
    return self._sex

@property
def sort_by(self):
    return self._sort_by

# noinspection SpellCheckingInspection
@sort_by.setter
def sort_by(self, key):
    # TODO: research a way to transform keys automatically in the dictionary
    # by parsing either the docstrings or attribute variables, check out functools
    if key in self.selection:
        self._sort_by = key

def __lt__(self, other):
    if isinstance(other, Person):
        if self._sort_by != other._sort_by:
            other._sort_by = self._sort_by

        if self.selection[self._sort_by] < other.selection[other._sort_by]:
            return True
        else:
            return False
    else:
        raise TypeError(f'Expected class Person got {type(other)}')

def __le__(self, other):
    if isinstance(other, Person):
        if self._sort_by != other._sort_by:
            other.sort_by = self.sort_by

        if self.selection[self._sort_by] <= other.selection[other._sort_by]:
            return True
        else:
            return False
    else:
        raise TypeError(f'Expected class Person got {type(other)}')

def __eq__(self, other):
    if isinstance(other, Person):
        if self._sort_by != other._sort_by:
            other._sort_by = self._sort_by

        if self.selection[self._sort_by] == other.selection[other._sort_by]:
            return True
        else:
            return False
    else:
        raise TypeError(f'Expected class Person got {type(other)}')

def __gt__(self, other):
    if isinstance(other, Person):
        if self._sort_by != other._sort_by:
            other._sort_by = self._sort_by

        if self.selection[self._sort_by] > other.selection[other._sort_by]:
            return True
        else:
            return False
    else:
        raise TypeError(f'Expected class Person got {type(other)}')

def __ge__(self, other):
    if isinstance(other, Person):
        if self._sort_by != other._sort_by:
            other._sort_by = self._sort_by

        if self.selection[self._sort_by] >= other.selection[other._sort_by]:
            return True
        else:
            return False
    else:
        raise TypeError(f'Expected class Person got {type(other)}')

def __repr__(self):
    return f'Person({self._first_name}, {self._middle_name}, ' \
           f'{self._last_name}, {self._dob}, {self._age}, ' \
           f'{self._sex}, {self._married}, {self._hair_color}, ' \
           f'{self._eye_color}, {self._weight}, ' \
           f'{self._height}, {self._sort_by})'

def __str__(self):
    return f'Name: {self._first_name} {self._middle_name} ' \
           f'{self._last_name}\nDate of Birth: {self._dob}\n' \
           f'Age: {self._age}\nSex: {self._sex}\nMarried: {self._married}\n' \
           f'Hair Color: {self._hair_color}\n' \
           f'Eye Color: {self._eye_color}\nWeight: {self._weight}\n' \
           f'Height: {self._height}\n)'

0 个答案:

没有答案