Сравнение кортежей Python
Есть метод для сравнение объектов Person
def compare_persons_less(person_left, person_right):
"""Return True if left < right."""
return (-person_left.count_task,person_left.count_fine,person_left.login) > (-
person_right.count_task, person_right.count_fine, person_right.login)
Выглядит элегантно, но работает медленнее аналога с кучей if-ов:
def compare_persons_less_2(person_left, person_right):
"""Return True if left < right."""
if person_left.count_task < person_right.count_task:
return True
if person_left.count_task > person_right.count_task:
return False
if person_left.count_task == person_right.count_task:
if person_left.count_fine > person_right.count_fine:
return True
if person_left.count_fine < person_right.count_fine:
return False
if person_left.count_fine == person_right.count_fine:
if person_left.login > person_right.login:
return True
if person_left.login < person_right.login:
return False
if person_left.login == person_right.login:
return False
Вопрос: как сделать так же элегантно, как в первом варианте и также быстро, как во втором?
Ответы (1 шт):
Автор решения: OPTIMUS PRIME
→ Ссылка
def compare(l: 'person_left', r: 'person_left'):
return (
l.count_task < r.count_task or
l.count_fine > r.count_fine or
l.login > r.login
)
Будет работать как ваш второй вариант, за счет особенности оператора or: Как только он встречает истинное значение, сразу же возвращает его, не вычисляя последующие выражения.
Тестил так:
from time import time
class Person:
def __init__(self, a, b, c):
self.count_task, self.count_fine, self.login = a, b, c
def test(fn):
start = time()
for _ in range(1000000): fn()
return time() - start
###
def compare_1(person_left, person_right):
"""Return True if left < right.""" """Return True if left < right."""
if person_left.count_task < person_right.count_task:
return True
if person_left.count_task > person_right.count_task:
return False
if person_left.count_task == person_right.count_task:
if person_left.count_fine > person_right.count_fine:
return True
if person_left.count_fine < person_right.count_fine:
return False
if person_left.count_fine == person_right.count_fine:
if person_left.login > person_right.login:
return True
if person_left.login < person_right.login:
return False
if person_left.login == person_right.login:
return False
def compare_2(l, r):
return (
l.count_task < r.count_task or
l.count_fine > r.count_fine or
l.login > r.login
)
x = Person(1, 2, 3)
y = Person(3, 4, 5)
for _ in range(10):
print( test(lambda: compare_1(x, y)), test(lambda: compare_2(x, y)) )