Telegram Group & Telegram Channel
🐍 Ошибка с изменяемыми значениями по умолчанию»**

🎯 Цель: Найти и объяснить баг, который не вызывает исключений, но ломает логику приложения

📍 Ситуация:

У тебя есть функция, которая логирует события с метаданными. По умолчанию метаданные можно не передавать:


def log_event(event, metadata={}):
metadata["event"] = event
print(metadata)


На первый взгляд — всё работает. Но при многократных вызовах функции происходит что-то странное:


log_event("start")
log_event("stop")
log_event("error", {"code": 500})
log_event("retry")


👀 Вывод:

{'event': 'start'}
{'event': 'stop'}
{'code': 500, 'event': 'error'}
{'code': 500, 'event': 'retry'}


🔍 Что пошло не так? Почему code: 500 появляется там, где его быть не должно?

🧩 Задача:

1. Найди и объясни источник бага
2. Почему Python не выбрасывает ошибку?
3. Как проверить, что дефолтный аргумент сохраняет состояние между вызовами?
4. Как это исправить безопасно и "по питоновски"?
5. Где ещё может проявиться аналогичный эффект?


🛠 Разбор и решение:

🔸 Причина:
Изменяемое значение (`dict`) используется как значение по умолчанию.
В Python значения по умолчанию вычисляются один раз при определении функции, а не при каждом вызове.

То есть
metadata={} создаётся один раз и сохраняется между вызовами, если параметр не передан.

🔸 Проверка:

def f(d={}):
print(id(d))
d["x"] = 1
print(d)

f()
f()


Вы увидишь одинаковые
id(d) — значит, используется тот же объект.

🔸 Решение (правильный способ):

def log_event(event, metadata=None):
if metadata is None:
metadata = {}
metadata["event"] = event
print(metadata)


Теперь при каждом вызове создаётся новый словарь, и
code: 500 не "протекает" в следующие вызовы.

🔸 Где ещё встречается:
- Списки:
items=[]
- Множества:
visited=set()
- Объекты пользовательских классов

📌 Вывод:
Изменяемые значения по умолчанию — одна из самых частых ошибок в Python. Она не вызывает исключений, но может незаметно повредить данные. Всегда используй
None + инициализацию внутри функции для изменяемых типов.

@pythonl



tg-me.com/pythonl/4839
Create:
Last Update:

🐍 Ошибка с изменяемыми значениями по умолчанию»**

🎯 Цель: Найти и объяснить баг, который не вызывает исключений, но ломает логику приложения

📍 Ситуация:

У тебя есть функция, которая логирует события с метаданными. По умолчанию метаданные можно не передавать:


def log_event(event, metadata={}):
metadata["event"] = event
print(metadata)


На первый взгляд — всё работает. Но при многократных вызовах функции происходит что-то странное:


log_event("start")
log_event("stop")
log_event("error", {"code": 500})
log_event("retry")


👀 Вывод:

{'event': 'start'}
{'event': 'stop'}
{'code': 500, 'event': 'error'}
{'code': 500, 'event': 'retry'}


🔍 Что пошло не так? Почему code: 500 появляется там, где его быть не должно?

🧩 Задача:

1. Найди и объясни источник бага
2. Почему Python не выбрасывает ошибку?
3. Как проверить, что дефолтный аргумент сохраняет состояние между вызовами?
4. Как это исправить безопасно и "по питоновски"?
5. Где ещё может проявиться аналогичный эффект?


🛠 Разбор и решение:

🔸 Причина:
Изменяемое значение (`dict`) используется как значение по умолчанию.
В Python значения по умолчанию вычисляются один раз при определении функции, а не при каждом вызове.

То есть
metadata={} создаётся один раз и сохраняется между вызовами, если параметр не передан.

🔸 Проверка:

def f(d={}):
print(id(d))
d["x"] = 1
print(d)

f()
f()


Вы увидишь одинаковые
id(d) — значит, используется тот же объект.

🔸 Решение (правильный способ):

def log_event(event, metadata=None):
if metadata is None:
metadata = {}
metadata["event"] = event
print(metadata)


Теперь при каждом вызове создаётся новый словарь, и
code: 500 не "протекает" в следующие вызовы.

🔸 Где ещё встречается:
- Списки:
items=[]
- Множества:
visited=set()
- Объекты пользовательских классов

📌 Вывод:
Изменяемые значения по умолчанию — одна из самых частых ошибок в Python. Она не вызывает исключений, но может незаметно повредить данные. Всегда используй
None + инициализацию внутри функции для изменяемых типов.

@pythonl

BY Python/ django


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/pythonl/4839

View MORE
Open in Telegram


Python django Telegram | DID YOU KNOW?

Date: |

If riding a bucking bronco is your idea of fun, you’re going to love what the stock market has in store. Consider this past week’s ride a preview.The week’s action didn’t look like much, if you didn’t know better. The Dow Jones Industrial Average rose 213.12 points or 0.6%, while the S&P 500 advanced 0.5%, and the Nasdaq Composite ended little changed.

Python django from nl


Telegram Python/ django
FROM USA