Python - один из самых популярных языков программирования. Как мы писали, в январе 2022 года он во второй раз за свою историю стал лидером ежемесячного рейтинга языков программирования Tiobe. Рост популярности Python за год составил 1,86%.
Популярность языка обусловлена его относительной простотой - работать с ним может быстро начать даже новичок. Конечно, никто не говорит, что этот новичок сможет сразу же писать высоконагруженные проекты, нет. Но решать задачи базового уровня - вполне. Но все же есть проблемы даже здесь, и о них поговорим в статье. Разбираем подводные камни Python вместе с Алексеем Некрасовым, лидером направления Python в МТС, программным директором направления Python и спикером профессии “Python-разработчик” в Skillbox.
Немного о достоинствах языка
На Хабре очень много статей о достоинствах Python, поэтому повторяться не будем. Скажем только, что язык действительно знаменит своей простотой. Причем с течением времени в нём появилось много “синтаксического сахара”, который позволяет быть ему немногословным и понятным языком, похожим на псевдокод. А всё сложное убрано “под капот”, чтобы не отвлекать разработчика. Простота позволяет быстро создавать прототипы и проверять гипотезы. Благодаря этому новичкам проще всего начать изучать программирование с Python.
Что такое синтаксический сахар? Это набор синтаксических конструкций, применение которых не влияет на поведение программы, но делает использование языка более удобным для человека. Например, паттерн “декоратор”:
def decorator_log(func):
def wrapper(*args, **kwargs):
print("вызов функции с параметрами", args, kwargs)
res = func(*args, **kwargs)
return res
return wrapper
def func_1():
print('Тестовая функция')
func_1 = decorator_log(func_1)
# Вместо func_1 = decorator_log(func_1) можно теперь написать:
@decorator_log
def func_1()
print('Тестовая функция')
Таких конструкций в языке достаточно много, они упрощают чтение кода и работу с ним.
Интерпретатор Python берёт на себя всю скучную и сложную работу по управлению памятью, потоками и т.д. Но есть и проблема. Дело в том, что из-за всех этих приятных плюсов Python теряет в скорости по сравнению с другими языками программирования.
Подробно о проблемах
Кроме потерь в скорости есть и другие подводные камни, о которых далеко не всегда знают начинающие разработчики. Среди них особенно выделяются две крупные проблемы, это динамическая типизация и так называемый "новый сахар".
Динамическая типизация
Python - динамически типизированный язык программирования. Это позволяет быстро разрабатывать прототипы и писать код. Динамическая типизация, если объяснять “на пальцах”, значит, что одна и та же переменная в разное время может ссылаться на данные разного типа. Например:
data = input() or '123456' # сейчас в переменной data лежит строка
data = int(data) # теперь в переменной data лежит целое число
И это будет работать.
Статистические языки программирования, например C, такого сделать не позволяют. Но в динамической типизации есть подвох. Если в простых проектах все ок и проблем не возникает, то, чем масштабнее проект на Python, тем больше появляется ошибок, связанных с типом переменных. Так, где-то далеко в коде введена функция, которая на вход принимает переменную data, введенную пользователем. В функции проверили, что введенное число является двузначным:
if len(data) != 2: print("Нужно ввести двухзначное число")
При выполнении этого кода мы внезапно получаем ошибку
if len(data) != 2: TypeError: object of type 'int' has no len()
Это означает, что в каком-то участке нашего кода строка уже переведена в число, и добавлена в переменную data. Подобные ошибки - далеко не редкость. Чаще всего они возникают на проектах, где работает от двух человек. Для того, чтобы ошибок не было, необходимо писать тесты, которые проверяют, нужный ли формат данных у переменных. У статических языков программирования таких проблем нет.
Еще один вариант решения - использование псевдостатической типизации и ее проверки при помощи статического анализатора mypy. Если проблемы с типами данных не нужны, то потребуется писать код следующим образом:
data: str = input() or '123456'
number: int = int(data)
if len(number) != 2:
print("Нужно ввести двухзначное число")
После написания кода приходится запускать для проверки mypy. Система проверяет, что int как строка нигде не используется. И если запустить mypy, то появится ошибка о передаче неверной переменной в функцию len:
error: Argument 1 to "len" has incompatible type "int"; expected "Sized"
Почему здесь употребляется термин "псевдостатическая типизация"? Дело в том, что при запуске скрипта Python проверка не будет проводиться сразу же, так что разработчик не будет знать, корректно ли выполняется передача значения в функцию len или нет. Ошибка появится лишь тогда, когда будет запущена программа с передачей в нее входного значения.
Новый сахар и усложнения в языке
Python постоянно развивается, в каждой новой версии языка появляется что-то новое, что упрощает разработчикам жизнь, позволяя решить задачу кодом с меньшим количеством строк, чем раньше. Но здесь и кроется проблема - программист может увлечься созданием конструкций, которые занимают меньше строк кода, но при этом и значительно уменьшают его читаемость.
Пример - задача по очистке входных данных с приведением их к целым числам. Раньше код программы выглядел бы следующим образом:
from typing import Optional
def to_int(string: str) -> Optional[int]:
try:
return int(string)
except ValueError:
return None
data = ['sadf', '12', '1', 'a1']
filter_data = []
for i_str in data:
i_number = to_int(i_str)
if i_number is not None:
filter_data.append(i_number)
print(filter_data)
Но начиная с версии 3.8 блок с for вполне можно записать следующим образом:
filter_data = [y for x in data if (y := to_int(x)) is not None]
Опытный разработчик в этом разберется без проблем, но для новичка чтение кода будет сложной задачей.
Какие еще есть сложности?
В целом, их не так мало. Обучение Python можно разделить на несколько этапов, и на каждом из них будут встречаться проблемы. Что касается этапов, то вот они:
Изучение простого синтаксиса, типов данных, функций, классов и т.д. На этом этапе нужно научиться понимать простые типы и структуры данных, а также “набить руку” на решении множества простых задач.
Изучение паттернов, которые реализованы уже в самом языке: декораторы, итераторы, генераторы, контекст менеджеры и т.д. На этом этапе идет осознание паттернов проектирования и как они реализованы в самом языке. Тут новичку из другой сферы будет непросто, но часто в осознании этих тем помогают наставники или хорошо подобранные статьи.
Изучение различных прикладных фреймворков: web (flask, FastApi, Django и др.), работа с БД (SQLAlchemy, sqlite3, Tortoise ORM и др.), работа с данными (numpy, pandas, marshmallow, pydantic и др.) и т.д. Здесь сталкиваемся со сложностью в определении направления своего развития и выстраивания своего маршрута в изучении доп. инструментов. Новичкам я бы посоветовал для этого проконсультироваться с опытным разработчиком или наставником.
Углублённое изучение языка: метаклассы, дескрипторы и т.д. В обычной работе разработчик с этим практически не встречается, так как 90% всех задач можно решить без этих знаний. Но если вы хотите стать первоклассным разработчиком, то этих тем вам не обойти.
В целом, обойти проблемы помогает постоянное обучение, а также более опытные коллеги и наставники. Не бойтесь обращаться к ним за помощью, как говориться: “Не тот глуп, кто не знает, но тот, кто знать не хочет.” К слову, если у вас возникли проблемы на каком-то из этих этапов, можете писать мне, постараюсь помочь.
А что насчет перспектив языка?
Если коротко, то с уверенностью могу сказать - они есть, изучать Python стоит, не сомневайтесь.
Если же расписать подробнее, то скажу, что с каждым годом требования для новичков со стороны работодателей возрастают. Все дело в том, что появляются новые фреймворки, более сложные версии языка программирования, новые инструменты и т.д.
Пять лет назад, чтобы устроиться junior python web-разработчиком нужно было уметь решать алгоритмические задачи и знать основы языка программирования. А сейчас добавилось следующее:
знание одного из фреймворка Flask/Django (желательно ещё и асинхронного фреймворка, например, FastAPI);
знание SQL и работа с PostgreSQL;
знание тестовых фреймворков pytest, unittest;
знание принципов контейнеризации и работы с docker;
знание основ Linux.
В ближайшее три-пять лет спрос будет расти на middle и senior разработчиков, так как именно они выполняют основную часть задач в IT-компаниях. Если смотреть на спрос стажёров/junior, то тут всё сложнее по следующим причинам:
Junior разработчик приносит только убыток компании, так ему нужен наставник (уровня middle/senior). В итоге на решение определенной задачи с учеником тратится больше времени, чем если бы задачу делал сам наставник.
Часто через полгода-год стажер/junior уходит из компании, в которой обучался, в другую с увеличением зарплаты в среднем в 2 раза. Соответственно, терпит убытки компания, которая первой наняла молодого специалиста на работу.
Завышенные ожидания у стажёров/junior. Многие переходят из других сфер, где они уже привыкли к своему доходу и не готовы переходить, к примеру, со 100 тыс. руб в месяц на 50 тыс. руб.
Через три-четыре года у стажёров/junior начнёт появляться конкурент в лице ИИ. Недавно компания DeepMind (дочка Alphabet), выполнила на платформе Codeforces 10 тестов и попала в 54% лучших участников. Вполне вероятно, что в скором будущем ИИ сможет решать простые, шаблонные задачи, которые в обычной ситуации дают стажерам/junior-разработчикам.
В качестве вывода
Подводя итог, мы видим, что если вы хотите перейти в сферу IT как python-разработчик, то вам нужно:
Максимально сконцентрировать свои силы на обучении, учиться предстоит многому, это будет занимать время.
Быть готовым тому, что в течение полугода-года ваша зарплата не превысит 100 тыс. руб. в месяц.
Постараться устроиться на первую работу и начать учиться у более опытных коллег.
Не стоит пугаться вышесказанного, изучение Python часто позволяет внедрить автоматизацию в ту сферу, в которой вы уже работаете. Это повышает вашу ценность на текущей работе как специалиста, а также позволяет автоматизировать часть рутинных задач. Плюс ко всему, вы получаете коммерческий опыт разработки.