Skip to content

Instantly share code, notes, and snippets.

@DJWOMS
Created March 31, 2026 11:36
Show Gist options
  • Select an option

  • Save DJWOMS/3ce2c640c98e6493c06adc0df883a51a to your computer and use it in GitHub Desktop.

Select an option

Save DJWOMS/3ce2c640c98e6493c06adc0df883a51a to your computer and use it in GitHub Desktop.
Ревью кода студента, калькулятор калорий и денег
import datetime as dt
class Record:
# Лучше использовать date=None вместо date=''.
# None явно означает "не передано", пустая строка это конкретное значение.
# Ниже проверка `not date` сработает одинаково для '' и None,
# но с None код читается понятнее.
def __init__(self, amount, comment, date=None):
self.amount = amount
# Форматирование тернарного оператора затрудняет чтение.
# if not и date разбиты на разные строки без причины.
# Лучше писать в одну строку или разбить на обычный if/else.
# Например:
# if date is None:
# self.date = dt.datetime.now().date()
# else:
# self.date = dt.datetime.strptime(date, '%d.%m.%Y').date()
self.date = (
dt.datetime.now().date() if
not
date else dt.datetime.strptime(date, '%d.%m.%Y').date())
self.comment = comment
class Calculator:
def __init__(self, limit):
self.limit = limit
self.records = []
def add_record(self, record):
self.records.append(record)
def get_today_stats(self):
today_stats = 0
# Переменная цикла названа Record с большой буквы это перекрывает
# имя класса Record в текущей области видимости.
# Используй строчную букву: for record in self.records.
for Record in self.records:
# dt.datetime.now().date() вызывается на каждой итерации цикла.
# Лучше вычислить один раз до цикла и сохранить в переменную,
# как это сделано в get_week_stats.
if Record.date == dt.datetime.now().date():
# Используй оператор += для единообразия с get_week_stats.
# today_stats += Record.amount
today_stats = today_stats + Record.amount
return today_stats
def get_week_stats(self):
week_stats = 0
today = dt.datetime.now().date()
for record in self.records:
if (
# (today - record.date).days вычисляется дважды.
# Сохрани в переменную: days_ago = (today - record.date).days
# и используй её в условии.
# Также можно записать условие короче:
# 0 <= (today - record.date).days < 7
(today - record.date).days < 7 and
(today - record.date).days >= 0
):
week_stats += record.amount
return week_stats
class CaloriesCalculator(Calculator):
# Комментарий должен быть оформлен как docstring, а не строчный комментарий.
# Например:
# def get_calories_remained(self):
# """Возвращает количество калорий, доступных сегодня к употреблению."""
def get_calories_remained(self): # Получает остаток калорий на сегодня
# Название переменной x не описывает её смысл.
# Используй что-то понятное calories_remained или remained.
x = self.limit - self.get_today_stats()
if x > 0:
# Для переноса строк не используй бэкслеш это нарушение требований.
# Оберни строку в скобки:
# return (
# f'Сегодня можно съесть что-нибудь ещё, '
# f'но с общей калорийностью не более {x} кКал'
# )
return f'Сегодня можно съесть что-нибудь' \
f' ещё, но с общей калорийностью не более {x} кКал'
# Ветка else здесь лишняя, if выше заканчивается return,
# значит всё что ниже выполнится только если условие ложно.
# Убери else и оставь просто return.
else:
# Лишние скобки в return, return не функция.
# Пиши return 'Хватит есть!'
return('Хватит есть!')
class CashCalculator(Calculator):
# float(60) избыточно. Пиши просто 60.0 или 60.
# Комментарии к константам лучше оформить как строки с точкой в конце
# или убрать совсем, имена USD_RATE и EURO_RATE говорят сами за себя.
USD_RATE = float(60) # Курс доллар США.
EURO_RATE = float(70) # Курс Евро.
# USD_RATE и EURO_RATE передавать как параметры со значениями по умолчанию
# не нужно, они уже доступны как атрибуты класса через self.USD_RATE
# и self.EURO_RATE. Такая сигнатура создаёт путаницу и позволяет
# случайно переопределить курс при вызове метода.
def get_today_cash_remained(self, currency,
USD_RATE=USD_RATE, EURO_RATE=EURO_RATE):
# currency_type = currency это лишнее присвоение, если всё равно
# переопределяешь значение в каждой ветке if/elif.
currency_type = currency
cash_remained = self.limit - self.get_today_stats()
# Первое условие проверяет currency, остальные currency_type.
# Это непоследовательно, хотя в данном случае значения совпадают.
# Используй одну переменную везде.
if currency == 'usd':
cash_remained /= USD_RATE
currency_type = 'USD'
elif currency_type == 'eur':
cash_remained /= EURO_RATE
currency_type = 'Euro'
elif currency_type == 'rub':
# КРИТИЧЕСКАЯ ОШИБКА здесь сравнение (==), а не присвоение (=).
# Эта строка ничего не делает, результат сравнения нигде не
# используется, cash_remained не изменяется.
# Для рублей конвертация не нужна, но если она подразумевалась
# используй =.
cash_remained == 1.00
currency_type = 'руб'
if cash_remained > 0:
return (
# Вызов round() внутри f-строки нарушает требования:
# "в f-строках нет вызовов функций".
# Вычисли значение до f-строки:
# rounded = round(cash_remained, 2)
# и используй {rounded} в строке.
f'На сегодня осталось {round(cash_remained, 2)} '
f'{currency_type}'
)
elif cash_remained == 0:
return 'Денег нет, держись'
# Последний elif можно заменить на else, так как других вариантов нет.
elif cash_remained < 0:
# Два нарушения сразу: бэкслеш для переноса и смешивание
# f-строк с .format() в одном методе это непоследовательно.
# Используй f-строку и скобки для переноса
# return (
# f'Денег нет, держись: '
# f'твой долг - {-cash_remained:.2f} {currency_type}'
# )
return 'Денег нет, держись:' \
' твой долг - {0:.2f} {1}'.format(-cash_remained,
currency_type)
# Этот метод не нужен, он вызывает родительский get_week_stats,
# но не возвращает результат, нет return.
# Если цель просто использовать родительскую реализацию,
# достаточно убрать этот метод целиком и он будет унаследован автоматически.
def get_week_stats(self):
super().get_week_stats()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment