Помогите сделать код проще

Write a function called check_date. check_date should require two positional parameters: a string representing the name of a month, and an integer representing a date. check_date should also have a keyword parameter called is_leap_year, assumed to be False, representing whether or not it's a leap year. Return True if the date is a valid calendar date. Return False if it is not. A date may not be a valid calendar date if the month isn't a real month, or if that date does not exist for that month. You can see some examples at the end of this file. Remember: 30 days has September, April, June, and November. All the rest have 31, except February, which has 28, until Leap Year gives it 29. You may assume that day will be greater than 0 (you don't need to check negative or zero values for day)

Для решения задачи, описанной выше написал следующий код:

def check_date(name_month, date, is_leap_year = False):
    if date in range (1,30) and is_leap_year == True and name_month == "February":
        return True
    elif date in range (1, 32) and name_month in ("October", "January", "August", "December", "March", "July"):
        return True
    elif date in range (1, 31) and name_month in ("September", "April", "June", "November"):
        return True
    elif name_month not in ("October", "January", "August", "December", "March", "July", "September", "April", "June", "November", "February"):
        return False
    else:
        return False
print(check_date("January", 31))
print(check_date("February", 29, is_leap_year = True))
print(check_date("Techtember", 15, is_leap_year = True))
print(check_date("June", 31))

Все прекрасно работает, но мне он не нравится - слишком много условий.
Подскажите как сделать код более простым?

PS Я новичок в изучении Python.
PPS Спасибо!


Ответы (2 шт):

Автор решения: alex

крадем из модуля datetime _MONTHNAMES и _DAYS_IN_MONTH

def check_date(name_month, date, is_leap_year=False):
    _MONTHNAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

    if is_leap_year:
        _DAYS_IN_MONTH[1] = 29

    days_in_month = _DAYS_IN_MONTH[_MONTHNAMES.index(name_month)]
    return 0 < date <= days_in_month


print(check_date("Jan", 31))
print(check_date("Feb", 29, is_leap_year=True))
print(check_date("Feb", 28, is_leap_year=True))
print(check_date("Feb", 28))
print(check_date("Dec", 15, is_leap_year=True))
print(check_date("Jun", 31))
→ Ссылка
Автор решения: Jack_oS

Мне больше нравится через словари:

def check_date(name_month: str, date: int, is_leap_year=False) -> bool:
    calendar = {'January': 31, 'February': 28, 'March': 31, 'April': 30, 'May': 31, 'June': 30, 'July': 31, 'August': 31, 'September': 30, 'October': 31, 'November': 30, 'December': 31,}

    if is_leap_year:
        calendar['February'] = 29

    return date <= calendar.get(name_month, False)

Нужно только установить максимальную дату февраля 29-е, если год високосный...

>>> check_date("January", 31)
True
>>> check_date("February", 29, is_leap_year = True)
True
>>> check_date("Techtember", 15, is_leap_year = True)
False
>>> check_date("June", 31)
False

dict.get() вернет значение по ключу, либо default (необязательный параметр, None по-умолчанию): если месяц есть в словаре - вернет значение (дней), иначе вернет False (установленный вместо default)... дальше сравнивается date и то, что вернул dict.get() (инты с булевыми сравниваются в пайтоне преобразованием булевого в 1 или 0)

→ Ссылка