Добавить в корзинуПозвонить
Найти в Дзене
NeyroProfit

Ошибки новичков в Python: 7 граблей, на которые наступают все

Python прощают многое. Но некоторые ошибки новички совершают с завидным постоянством. Я и сам наступал на эти грабли — разбираем, как обойти. Классика. Смотри: ```python def add_item(item, lst=[]): lst.append(item) return lst print(add_item(1)) # [1] print(add_item(2)) # [1, 2] — упс! ``` Список `lst` создаётся один раз при определении функции. Каждый вызов использует один и тот же список. Ожидаешь пустой список, а получаешь всё накопленное. Как правильно: ```python def add_item(item, lst=None): if lst is None: lst = [] lst.append(item) return lst ``` То же самое с `{}`, `set()` и любыми изменяемыми типами. Никогда не ставь их в аргументы по умолчанию. `==` проверяет равенство значений. `is` проверяет, что это один и тот же объект в памяти. ```python a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True — значения совпадают print(a is b) # False — разные объекты ``` С числами работает хитро: маленькие числа Python кеширует, поэтому `a = 5; b = 5; a is b` может вернуть `True`. А с `256` — уж
Оглавление

Python прощают многое. Но некоторые ошибки новички совершают с завидным постоянством. Я и сам наступал на эти грабли — разбираем, как обойти.

№1. Изменяемый объект как аргумент по умолчанию

Классика. Смотри:

```python

def add_item(item, lst=[]):

lst.append(item)

return lst

print(add_item(1)) # [1]

print(add_item(2)) # [1, 2] — упс!

```

Список `lst` создаётся один раз при определении функции. Каждый вызов использует один и тот же список. Ожидаешь пустой список, а получаешь всё накопленное.

Как правильно:

```python

def add_item(item, lst=None):

if lst is None:

lst = []

lst.append(item)

return lst

```

То же самое с `{}`, `set()` и любыми изменяемыми типами. Никогда не ставь их в аргументы по умолчанию.

№2. Путаница между `==` и `is`

`==` проверяет равенство значений. `is` проверяет, что это один и тот же объект в памяти.

```python

a = [1, 2, 3]

b = [1, 2, 3]

print(a == b) # True — значения совпадают

print(a is b) # False — разные объекты

```

С числами работает хитро: маленькие числа Python кеширует, поэтому `a = 5; b = 5; a is b` может вернуть `True`. А с `256` — уже `False`. Не гадай, используй `==` для сравнения значений.

№3. Забытый `return`

Самая частая причина «функция вернула None». Ты написал функцию, а забыл `return`:

```python

def square(n):

result = n * n

return забыт!

val = square(5)

print(val) # None

```

Python по умолчанию возвращает `None`, если `return` не указан. Правило: если функция должна что-то отдавать — пиши `return`.

№4. Изменение списка во время итерации

```python

nums = [1, 2, 3, 4, 5]

for n in nums:

if n % 2 == 0:

nums.remove(n)

print(nums) # [1, 3, 5] — повезло

```

Иногда работает, иногда пропускает элементы. Потому что после `remove` индексы сдвигаются.

Как правильно: создавай новый список.

```python

nums = [1, 2, 3, 4, 5]

nums = [n for n in nums if n % 2 != 0]

```

Или делай копию:

```python

for n in nums[:]: # срез — копия

if n % 2 == 0:

nums.remove(n)

```

№5. Глобальные переменные внутри функции

```python

count = 0

def increment():

count += 1 # UnboundLocalError!

increment()

```

Когда ты присваиваешь значение переменной внутри функции, Python считает её локальной. Даже если снаружи есть такая же.

Как правильно: используй `global`.

```python

count = 0

def increment():

global count

count += 1

```

Но лучше вообще избегать глобальных переменных. Передавай параметры и возвращай результат.

№6. Голый `except`

```python

try:

result = 10 / 0

except:

print("Ошибка")

```

Кажется безобидным, но такой `except` ловит вообще всё: и `KeyboardInterrupt` (Ctrl+C), и `SystemExit`. Ты не сможешь прервать программу, пока она в этом блоке.

Как правильно: указывай конкретное исключение.

```python

try:

result = 10 / 0

except ZeroDivisionError:

print("Деление на ноль")

```

Или хотя бы `except Exception` — он не ловит системные исключения.

№7. Мутабельные переменные как копии

```python

original = {"name": "Аня", "age": 25}

copy = original

copy["age"] = 30

print(original) # {'name': 'Аня', 'age': 30} — тоже изменилось!

```

Переменная `copy` — не копия, а ещё одна ссылка на тот же словарь. Меняешь через одну — меняется везде.

Как правильно: делай глубокую копию.

```python

copy = original.copy() # для словарей и списков

или

import copy

copy = copy.deepcopy(original) # для вложенных структур

```

Вывод

Семь граблей, через которые проходит каждый. Хорошая новость: один раз наступил — запомнил навсегда. Сохрани эту статью в закладки и возвращайся, когда поймаешь странный баг. Скорее всего, это одна из этих ошибок.

А на какие грабли наступал ты? Делись в комментариях.