Дата по умолчанию соответствует дате начала веб-сервера Django, а не параметру метода по умолчанию

Я наткнулся на нечто неожиданное, возможно, это что-то базовое, что я неправильно понимаю либо в Python, либо в Django.

У меня есть статический метод в классе модели, который возвращает дату, указанную пользователем, или альтернативно возвращает сегодняшнюю дату:

    @staticmethod
    # By default return today's date or the date provided
    def get_start_date(**kwargs):
        startDate = kwargs.get('startDate', datetime.date.today())
        return startDate

Я решил переписать его так, чтобы метод имел startDate в качестве параметра по умолчанию. Однако вместо сегодняшней даты по умолчанию используется дата первого запуска веб-сервера Django. Почему так происходит? Метод выполняется, я подтверждаю, что startDate не был указан в вызове, даже когда в качестве аргумента вводится переменная, которая, как я точно знаю, больше нигде в коде не используется, все равно возвращается дата первого запуска Django.

    def get_start_date(startDate=datetime.date.today(), notUsed=datetime.date.today(), **kwargs):
        print(startDate, notUsed, datetime.date.today())
        return startDate

    >>> 2022-06-23 2022-06-23 2022-06-24

Аргументы по умолчанию в Python оцениваются один раз при определении функции, а не при каждом вызове функции. Это означает, что если вы используете мутабельный аргумент по умолчанию и мутируете его, вы будете и уже мутировали этот объект для всех последующих вызовов функции.

Итак, измените определение вашей функции на

def my_function(start_date=datetime.date.today()):
    # do something

to

def my_function(start_date=None):
    if start_date is None:
        start_date = datetime.date.today()
    # do something
Вернуться на верх