Español
Abrir en Telegram
PPYTHON IN DEPTH🐍

PYTHON IN DEPTH🐍

@python_in_depth · canal · Tecnología · indexada desde 2026-07-04
385suscriptores
50alcance medio por publicación
2publicaciones en 30 días
41publicaciones en el índice
P
PYTHON IN DEPTH🐍
Странная переменная в Python. Когда человек впервые видит в программе что-то вроде _, v in my_dict.items(): pass он обычно теряется. Что это за переменная “_”? В командной строке интерпретатора нижнее подчеркивание хранит значение последнего выражения. Пользоваться ей можно вот так: >>> a + b 20 >>> _ 20 >>> _ * 2 40 В интерпретаторе это позволяет вообще не писать названия переменных и работать быстрее: >>> list() [] >>> _.append(‘чепуха’) >>> _.append(‘небылица’) >>> _.append(‘выдумка’) >>> _ [‘чепуха’, ‘небылица’, ‘выдумка’] При этом _ -- абсолютно валидное имя. Настолько, что в скриптах его принято использовать для dummy-переменных, значениями которых пользоваться не собираются. Например: for _ in range(4): print(“Шутка, повторенная дважды, становится в 4 раза смешнее”) Или вот так: _, c = ['чепуха', 'небылица', 'выдумка'] print(‘{} {}’.format(a, c)) 'чепуха, выдумка' С другой стороны, если заводите переменную, значение которой вам не нужно, подумайте, стоит ли вообще это делать. В самом первом примере for _, v in my_dict.items(): pass можно было с тем же успехом использовать values(). В общем, в Python у переменной _ две функции: 🥳 она хранит последнее вычисленное интерпретатором значение, 🥳 и ее принято использовать, чтобы проигнорировать значение переменной.
234 ·
P
PYTHON IN DEPTH🐍
Одинарное подчеркивание в конце переменной Недавно говорила об одинарном символе подчеркивания в Python. Теперь поговорим о подчеркивании в конце переменной: my_argument_ = 10 Нет никаких причин так делать, кроме одной: имя, которое вы хотите дать переменной, конфликтурет с именем встроенной функции или ключевого слова в Python. В PEP8, документе, который закрепляет соглашения по кодстайлу в Python, написано следующее: single_trailing_underscore_: используется по соглашению для избежания конфликтов с ключевыми словами языка, например: Tkinter.Toplevel(master, class_='ClassName') Поэтому в этом примере лучше просто написать my_argument, без подчеркивания. А вот если вам понадобится, например, что-то из id, class, del, ..., то можно добавить _. Правда, даже в этом случае я сама обычно выбираю более объясняющее имя, например, person_id, class_name, delimeter, чтобы не путать коллег и сделать код более читаемым. В общем, в Python есть соглашение по использованию подчеркивания в конце переменной. Подчеркивание обычно добавляют, когда название переменной конфликтует с уже занятыми интерпретатором именами. Мое мнение, что в случае конфликта лучше просто попытаться выбрать другое имя.
251 ·
P
PYTHON IN DEPTH🐍
List astonishment Допустим, мы хотим написать функцию, которая будет принимать на вход список. Естественным ходом выглядит написать что-то вроде: >>> def foo(data=[]): ... data.append(5) ... return data Ждем, что при каждом новом вызовы функции список снова будет пустым. На самом же деле: >>> foo() [5] >>> foo() [5, 5] >>> foo() [5, 5, 5] Вот это поворот! Причина такого поведения в том, что в Python значения дефолтных аргументов вычисляются только один раз -- при объявлении функции. То есть, после того, как инструкция def выполнена, список data уже создан. При этом пока функция существует, пересоздаваться список больше не будет. Это объясняет и вот такое поведение: >>> foo(data=[1, 2, 3]) [1, 2, 3, 5] >>> foo() [5, 5, 5] Видно, что, когда мы передали другой список в foo(), к нему добавилось значение 5. При этом аргумент по умолчанию не изменился. Как с этим жить? Либо вообще не использовать изменяемые объекты в качестве дефолтных значний, либо инициализировать их как None: >>> def bar(data=None): ... if data is None: ... data = [] ... data.append(5) ... return data Такое определение создает новый список в локальном неймспейсе. Теперь все чисто😏 >>> bar() [5] >>> bar() [5] >>> bar(data=[1, 2, 3]) [1, 2, 3, 5] На самом деле это поведение можно обратить в свою пользу. Пусть, например, в программе есть функция, которая долго вычисляет результат. Можно кешировать параметры и результат вычисления, и, если функцию вызывают еще раз с теми же парметрами, просто возвращать заранее посчитанный ответ. def baz(arg1, arg2, _cache={}): # Если есть в кеше, выходим if (arg1, arg2) in _cache: return _cache[(arg1, arg2)] # Вычисляем результат result = ... # Сохраняем в кеш _cache[(arg1, arg2)] = result return result Сохранение результатов для предотвращения повторных вычислений называется мемоизацией. В Python дефолтные аргументы инициализируются только при объявлении фун
2 · 312 ·
P
PYTHON IN DEPTH🐍
for ... else? Рассмотрим пример использования ключевого слова else в цикле while: >>> i = 1 >>> while i < 4: ... print(i) ... i += 1 ... else: ... print('Вышли из цикла!') Если выполнить этот цикл, то мы получим: 1 2 3 Вышли из цикла! Здесь блок else выполняется только тогда, когда условие выхода из цикла перестает быть верным. Особенность здесь в том, что если вывалиться из цикла через break или через исключение, то блок else выполняться не будет. Это работает не только с циклами while, но и с циклами for: >>> for value in values: ... if value == 4: ... print('Нашли!:)') ... break ... else: ... print('Не нашли:(') И так же можно с try-except блоками. На самом деле исключения в Python это не try-except-finally, а try-except-else-finally, ниже пример: >>> num = 0 >>> try: ... result = 1 / num ... except ZeroDivisionError: ... print('Деление на ноль!') ... else: ... print('Конечное число.') ... finally: ... print('Вычисления закончены.') ... Деление на ноль! Вычисления закончены. А если задать num = float('Inf'), то в результате деления мы получим 0 и вывод будет: Конечное число. Вычисления закончены. Блок finally выполняется в любом случае. А else можно использовать, если нужно выполниь еще какой-то код в случае отсутствия исключений. Например, это может быть полезно в тестах, когда мы хотим логгировать как в случае падения теста на исключении, так и в случае, если исключений брошено не было. В общем, есть конструкции while-else и for-else, в которых else отрабатывает в случае <<штатного>> завершения цикла. Еще else можно использовать в try-except блоке, чтобы выполнить какой-то код только в случае успешного выполнения блока try. Во всех случаях использование else позволяет более гибко управлять потоком выполнения 🐍
288 ·
P
PYTHON IN DEPTH🐍
Enlace
haz clic para mostrar
Timsort Для сортировки в CPython используется алгоритм Timsort, который его создатель Тим Петерс застенчиво назвал в честь себя😏. Timsort — это комбинация сортировки вставками и сортировки слиянием, заточенная под работу с реальными данными. Дело в том, что на практике массивы, которые нужно сортировать, часто бывают частично упорядочены и Timsort пользуется этим предположением для ускорения работы. Логика работы Timsort на самом деле довольно прозрачная: 🐠 Timsort делит входной массив на подмассивы; 🐠 Сортирует подмассивы вставками; 🐠 Объединяет их попарно сортировкой слиянием; 🐠 И возвращает отсортированный массив. Но дьявол кроется в деталях. Делим на подмассивы Части, на которые алгоритм делит входной массив, в описании алгоритма автор называет run'ами. Так на какое количество run'ов следует разделить входной массив? Здесь два соображения. Во-первых, части должны быть достаточно короткими, чтобы их было выгодно сортировать вставками. А еще мы хотим, чтобы пары последовательностей, которые позже поступят в сортировку слиянием, были примерно одинаковой длины. Дальше происходит магия, которая учитывает эти соображения и выбирает длину подпоследовательности minrun между 32 и 64 элементами. При этом если входной массив короче 64 элементов, то на части он не делится. Сортируем run'ы Перед тем, как приступить к сортировке подмассива, алгоритм ищет изначально упорядоченные участки. Если они слишком короткие и не дотягивают до минимального размера, то алгоритм удлинняет их бинарной сортировкой. Бинарная сортировка — это разновидность сортировки вставками, которая помещает элементы на свои места, используя двоичный поиск. Сортировки вставками как раз эффективны в случаях небольших частично упорядоченных массивов. Сам Петерс пишет, что это лучшее, что можно было выбрать, учитывая ограничения более утонченных алгоритмов. Сливаем подмассивы По мере того, как упорядоченные run'ы формируются, сортировкой слияния они объединяются попарно во всё более крупные отсорт
310 ·
P
PYTHON IN DEPTH🐍
Введение в множества Set' ы в Python реализованы так, что максимально напоминают математические множества. Давайте пройдемся по основным свойствам и возможностям множеств в Python, и разберемся, как их использовать. В математике множество -- это набор объектов произвольной природы. В Python множество тоже может содержать переменные разных типов, например: >>> A = {"My hovercraft is full of eels", 42, (3.14, 2.72)} Но есть одно ограничение: элементы множества должны быть хэшируемыми: например, в множество можно добавить строки, числа и кортежи, но нельзя словари и списки: >>> A.add([-1, 0]) TypeError: unhashable type: 'list' При этом поскольку сами множества мутабельны, то множество множеств, как в известном парадоксе про брадобрея, сделать не получится. Но если очень хочется, можно использовать frozenset’ы: эти объекты в остальном ведут себя почти так же, но они иммутабельны и их можно добавить в множество. Инициализировать множество можно используя фигурные скобки или через конструктор класса set(). Эти инициализации эквивалентны: >>> B = {1, 2, 3} >>> B = set((1, 2, 3)) Только не запутайтесь: такая инструкция C = {} создаст не множество, а словарь. В версиях интерпретатора 2.7 и выше работают set comprehensions: >>> C = {x for x in range(1, 5)} >>> C {1, 2, 3, 4} Элементы множества, как и в математике, должны быть уникальными. На практике этим пользуются для того, чтобы исключить повторяющиеся элементы: >>> D = [1, 2, 3, 3] >>> D = list(set(D)) >>> D [1, 2, 3] Кстати, множества не сохраняют порядок, поэтому если он нужен, то добро пожаловать в списки. Из-за того, что порядка нет, во множествах нет ни индексирования, ни слайсов. В то же время циклы по множеству можно делать обычным pythonic-способом: >>> for elem in C: ... print(elem) Над множествами в Python можно делать те же операции, что и в математике: находить объединение, пересечение, проверять принадлежность к множеству и так далее. Для этого можно пользоваться операт
398 ·
P
PYTHON IN DEPTH🐍
Умножение контейнеров Один интересный факт из Python. Вы, наверное, знали, что для строк определен оператор умножения и что можно делать так: >>> 'привет ' * 4 'привет привет привет привет ' То же, вообще говоря, работает с другими контейнерами, например, с кортежами: >>> ('привет',) * 3 ('привет', 'привет', 'привет') И с этим все хорошо, пока внутри контейнера не появляется ссылка на изменяемый объект. Например, на словарь: >>> d = [{'key': 'val'}] * 2 >>> d [{'key': 'val'}, {'key': 'val'}] Потому что теперь каждый из двух словарей доступен по одной и той же ссылке: >>> d[0]['key'] = '' >>> d [{'key': ''}, {'key': ''}] Упс, отстрелили себе ногу. Умножение -- это валидный способ создавать составные объекты только если вложенные неизменяемы. 🐠
308 ·
P
PYTHON IN DEPTH🐍
Enlace
haz clic para mostrar
Гид по множественному присваиванию Уверена, что множественное присваивание в Python видели все. Выглядит оно вот так: >>> x, y, z = 1, 2, 3 >>> x 1 >>> z 3 На самом деле на низком уровне создается tuple и в цикле инициализируется значениями 1, 2, 3. Поэтому с тем же успехом можно не опускать скобки и написать вот так: >>> (x, y, z) = (1, 2, 3) >>> x 1 >>> z 3 И это тоже сработает. Поэтому множественное присваивание еще называют tuple unpacking. Да и чаще всего его, кажется, используют именно с кортежами. Но вообще так можно писать с любыми iterable типами: >>> x, y = [1, 2] >>> y 2 И со строками тоже: >>> x, y = 'hi' >>> x 'h' >>> y 'i' Множественное присваивание, если применять его с оператором *, позволяет делать еще вот такие крутые штуки: >>> numbers = [1, 2, 3, 4, 5, 6] >>> first, *rest = numbers >>> first 1 >>> rest [2, 3, 4, 5, 6] По сути * здесь заменяет слайсы. С тем же успехом можно было написать: >>> first, last = numbers[0], numbers[1:] >>> first 1 >>> last [2, 3, 4, 5, 6] Но через распаковку получается читаемее. Можно даже <<вырезать>> середину: >>> first, *middle, last = numbers И если вам не нужны все промежуточные индексы, то хороший тон это вообще использовать нижнее подчеркивание: >>> first, *_, last = [1, 2, 3, 4, 5, 6] Кстати, если речь о вложенных объектах, то обратите внимание, что копия будет глубокой: >>> color, point = ('blue', (0, 0, 255)) >>> color 'blue' >>> point (0, 0, 255) В некоторых случаях это очень удобно. В общем, множественное присваивание можно использовать не только с кортежами, но и списками, строками и любыми iterable типами. Его плюс в том, что оно позволяет не использовать индексы, а значит, уменьшает склонность к ошибкам и делает код читаемее. А еще оно используется в <<args, kwargs>> синтаксисе, который часто смущает начинающих, но об этом в следующий раз. 🐠
457 ·
P
PYTHON IN DEPTH🐍
Введение в декораторы В нескольких следующих постах я хочу поговорить о декораторах. Будет базовое определение, мотивация их использовать, всякие хитрости, а еще куча примеров. Прежде, чем говорить о декораторах, нужно кое- что узнать о функциях в Python. Допустим, у нас есть функция, которая здоровается с Юпи: def hey_Jupi(): print("Привет, Юпи!") Функции в Python -- это объекты первого класса, ничем не хуже, чем int'ы или словари. Это значит, что: 🐙 Функцию можно присвоить переменной: say_hi = hey_Jupi say_hi() # Привет, Юпи! 🐙 Функцию можно вернуть из функции: def wrapper(func): print("Юпи пришла.") return func hello_Jupi = wrapper(hey_Jupi) # Юпи пришла. hello_Jupi() # Привет, Юпи! 🐙 Функцию можно определить внутри другой функции: def deco(func): def wrapper(): print("Юпи пришла.") func() return wrapper hey_Jupi = deco(hey_Jupi) hey_Jupi() # Юпи пришла. # Привет, Юпи! Смотрите, что получилось на последнем шаге. На этапе создания deco никакой код не выполняется -- мы заходим в deco, видим, что здесь определена функция wrapper и возвращаем ее. Таким образом мы подменяем исходную hey_Jupi на wrapper и получаем новое поведение hey_Jupi, не изменяя ее код! Это и называется декоратор. Это настолько удобный и мощный инструмент, что в Python для него придумали специальный синтаксический сахар. При условии, что функция deco у нас уже определена так же, как выше, можно добавить название декоратора с символом @ перед определением функции и получить эквивалентное поведение: @deco def hey_Jupi(): print("Привет, Юпи!") hey_Jupi() # Юпи пришла. # Привет, Юпи! Кстати, этот же декоратор можно применить и к любой другой функции: @deco def take_five(): print("Юпи, дай пять!") take_five() # Юпи пришла. # Юпи, дай пять! Декораторы круты тем, что позволяют гибко модифицировать поведение функции, применять одну и ту же модификацию к нескольким функциям сразу и даже менять поведение функций, доступа к коду кот
2 · 443 ·
P
PYTHON IN DEPTH🐍
Комбинируем декораторы Допустим, у нас есть функции, которые работают со строками. Возьмем, например, функцию, которая возвращает строчку из Zen of Python: def readability(): return 'Readability counts' print(readability()) Readability counts А теперь мы хотим, чтобы можно было показать текст в двух вариантах: жирным и курсивом. Вот два декоратора, один из которых добавляет тег <<жирный>>, а второй <<курсив>> : def bold(func): def wrapper(): return '<b>' + func() + '</b>' return wrapper def italic(func): def wrapper(): return '<i>' + func() + '</i>' return wrapper Как уже договаривались в прошлом посте запись: @bold def readable(): return 'Readability counts' Эквивалентна записи readable = bold(readable) И после применения декоратора вызов функции дает текст print(readable()) <b>Readability counts</b> А что если мы хотим получить текст одновременно и жирный и с курсивом? Можно сделать композицию декораторов: @italic @bold def readable(): return 'Readability counts' print(readable()) <i><b>Readability counts</b></i> Обратите внимание, что результат в зависимости от порядка применения декораторов будет разным: @bold @italic def readable(): return 'Readability counts' print(readable()) <b><i>Readability counts</i></b> Так получается из-за разного порядка выполнения функций: в первом случае мы сначала добавляем тэг <<жирный>>, а сверху оборачиваем в <<курсив>>: readable = italic(bold(readable)) А во втором -- наоборот: readable = bold(italic(readable))
1 · 572 ·
P
PYTHON IN DEPTH🐍
Исключения Представьте, вы приступаете к работе над новым проектом и обнаруживаете в логах следующие сообщения, которые смешаны с успешными запросами к серверу: Unexpected exception: Что-то постоянно ломается, но без каких-либо сообщений. Если сократить проблему до минимального примера из кода приложения, с которым я недавно столкнулся, получится следующая конструкция, которая на первый взгляд не вызывает подозрений: try: raise KeyError except Exception as e: print(f"Unexpected exception: {e}") При выполнении этого примера получим следующий результат: Unexpected exception: Проблема заключается в том, что есть четыре способа вывести сообщение об исключении: 🐟 print(e) 🐟 print(str(e)) 🐟 print(e.message) 🐟 print(repr(e)) Первые два варианта не особенно информативны. Например, если мы попытаемся обратиться к несуществующему ключу в словаре (самая распространенная ошибка в Python), то эти варианты выведут только название ключа. my_dict = {} try: b = my_dict["bad"] except Exception as e: print(f"Unexpected exception: {e}") Unexpected exception: 'bad' Это происходит потому, что str(e) и e выводят только сообщение об ошибке, но не ее тип. Чаще всего этого достаточно, но исключения существуют для того, чтобы информировать о ситуациях, которые не были ожидаемы. Иногда люди используют print(e.message). Однако здесь возникают две проблемы: во-первых, мы все равно получаем только сообщение об ошибке, а не ее тип. Во-вторых, атрибут message не определен для всех исключений. Если мы не проверим наличие этого атрибута перед использованием, мы получим новое исключение: AttributeError: 'KeyError' object has no attribute 'message' Однако магический метод repr, который используется для предоставления наиболее точного описания, справляется с задачей. Рассмотрим сравнение: try: raise KeyError except Exception as e: print(f"Unexpected exception: {repr(e)}") Unexpected exception: KeyError() В случае с использованием словаря получим: Unexpected exc
1 · 824 ·
P
PYTHON IN DEPTH🐍
Еще про исключения: repr(e) -- это, конечно хорошо, но ведь есть ещё лучше, а именно: from traceback import print_exc ... my_dict = {} try: b = my_dict["bad"] except Exception as e: print_exc() что выведет: Traceback (most recent call last): File "<pyshell#1>", line 2, in <module> KeyError: 'bad' и при этом программа продолжит свою работу. А если ошибку надо выводить не в stdout, то можно сделать так: from traceback import print_exc from io import StringIO ... try: b = my_dict["bad"] except Exception: buffer = StringIO() print_exc(file=buffer) out_var = buffer.getvalue()
1K ·
P
PYTHON IN DEPTH🐍
Дублирование объектов в множестве Предположим, у нас есть сервер и его клиенты. Мы хотим отслеживать состояние клиентов на сервере и управлять ими. Для этой цели мы будем добавлять клиентов в коллекцию, чтобы избежать случайного дублирования одного и того же клиента на сервере. Давайте создадим класс Client и добавим его в коллекцию (я также добавил метод repr для красивого вывода): class Client: def init(self, user_name): self.user_name = user_name def repr(self): return self.user_name fish1 = Client(user_name="catfish") clients = set() clients.add(fish1) print(clients) # {catfish} Замечательно, всё работает как задумано! Теперь попробуем добавить второго клиента и убедимся, что дублирования не происходит: fish2 = Client(user_name="catfish") clients.add(fish2) print(clients) # {catfish} Как это возможно? Мы добавили два абсолютно идентичных экземпляра в коллекцию, ожидая, что останется только один, но оба остались. При добавлении объекта в коллекцию интерпретатор следует следующему правилу: если a == b, то hash(a) == hash(b) должно быть обязательно выполнено. То есть, интерпретатор сравнивает объекты не только напрямую, но также сравнивает их хеши. Для сравнения объектов, коллекции и словари используют магический метод eq. Для пользовательских объектов этот метод определен по умолчанию. По умолчанию, два разных объекта не считаются равными, даже если они абсолютно идентичны: print(fish1 == fish2) # False По умолчанию все объекты в Python также имеют хеш-значение (хеш), которое рассчитывается из их идентификатора (id). Когда мы пытаемся добавить объект в коллекцию, мы используем магический метод hash этого объекта, который также определен по умолчанию. Часто люди думают, что хеш объекта совпадает с его адресом в памяти, но это не всегда так: 🦑 В Python 2.6 и более ранних версиях hash(x) = id() 🦑 В Python 2.6 и более поздних версиях: (https://bugs.python.org/issue5169) hash(x) == id(x)/16 То есть, нельзя полагаться на то, что hash(x
2 · 1.5K ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
🖥Microsoft интегрировала Python в Excel Все популярные библиотеки Python (pandas, statsmodels и matplotlib) стали доступны для создания графиков и диаграмм. Для реализации всего этого появилась новая функция "PY"
5 · 1.1K ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
Топ популярных горячих клавиш, для PyCharm: Ctrl + D — Дублировать строку, когда пишешь схожие строки, теперь нет надобности набирать их сначала или выделять и копировать. Ctrl + R — Решил переименовать класс? Изменит имя во всем проекте. Ctrl + Shift + N — Поиск класса или метода по всему проекту. Ctrl + Alt + M — Написали код, теперь захотели его обернуть в функцию, вот сочетание. Ctrl + Alt + S — Перейти в настройки. Ctrl + Y — Удалить строку. Ctrl + B — Переместиться к данному классу. Ctrl + F12 — Показывает структуру данных файла. Alt + F7 — Посмотреть где используется данный класс, метод или функция. Ctrl + Shift + U — Быстро изменить регистр слов. Ctrl + Alt + L — Быстрое форматирование кода по стандарту PEP 8. Ctrl + Shift + ↑ ↓ — Для быстрого перемещения строк или блоков. Ctrl + W — Выделить текущий блок.
37 · 1.6K ·
P
PYTHON IN DEPTH🐍
Вышла первая бета Django 5.0, а значит значимого изменения состава релиза уже не будет и можно смотреть, что завезли: 1. Много поддержки асинхронности - в contrib.auth, возможность получить и обработать asyncio.CancelledError внутри вьюхи, если клиент разорвал соединение до того, как мы закончили обрабатывать запрос, поддержка асинхронки в куче декораторов, асинхронная отправка сигналов, новые асинхронные методы у моделек 2. На первом месте довольно спорная фича - возможность показывать количество фильтруемых объектов в боковом фильтре в админке. Там под капотом COUNT и естественно на более-менее приличных объемах данных тормозить будет нечеловечески. Благо можно глобально отключить 3. Упрощенная шаблонизация для форм из коробки, для тех кто работает с html-формами код станет читабельнее (хотя думается мне, что те кто работает с большими формами уже давно что-то подобное у себя реализовали) 4. Возможность задавать дефолты на уровне базы данных 5. `GENERATED`-поля в моделях, значение которых рассчитывается на уровне БД 6. В Choice-полях теперь можно использовать словарь, вместо кортежей В общим никаких революций https://docs.djangoproject.com/en/5.0/releases/5.0/
2 · 1.2K ·
P
PYTHON IN DEPTH🐍
Enlace
haz clic para mostrar
Новости nogil. Steering Council принял PEP 703 - опциональный gil из коробки. На discuss.python.org большой пост про это, я приведу только заинтересовавшие меня моменты: Пока нет уверенности, что выпиливание gil не поломает совместимость со сторонними либами, не сделает интерпретатор медленнее на 10–15% и не усложнит его поддержку. Выбрали вполне ожидаемый подход - реализуем и посмотрим, как пойдет, потому что на прототипах и теоретических выкладках далеко не уедешь. Как и предполагали раньше, все будет происходить в несколько этапов: 1. Возможность отключить gil на этапе сборки — это точно не продакшен решение, а инструмент для авторов библиотек и экспериментаторов 2. Финализация изменений API и ABI, после чего nogil-сборка будет уже считаться не экспериментальной но все еще не включаться по дефолту 3. Отключенный gil по умолчанию с возможностью включить при сборке В общем планируют переходить очень постепенно и не загонять людей в светлое будущее палкой вплоть до того, что готовы отозвать PEP 703 если переход окажется слишком калечащим. https://discuss.python.org/t/pep-703-making-the-global-interpreter-lock-optional-in-cpython-acceptance/37075
1.5K ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
Еееееее, а че мы над js смеемся
3 · 587 ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
Интеграции с внешними системами: как не превратить backend в зоопарк адаптеров Рано или поздно backend обрастает интеграциями: платежи, CRM, учётные системы, доставка. Если не договориться с собой о правилах — код быстро начинает жить по законам чужих API. Несколько вещей, которые реально помогают не потерять контроль над архитектурой. 1. Anti-corruption layer Не смешивайте доменные модели с ответами партнёров. Лучше выделить отдельный слой. class PaymentGateway: async def create_payment(self, dto: PaymentDTO) -> Payment: ... Контракт у партнёра изменился — правки остаются в одном месте. 2. DTO как точка входа DTO — удобное место для валидации и нормализации данных. @dataclass class PartnerOrderDTO: external_id: str total: Decimal На этом этапе проще отфильтровать неконсистентные данные, чем ловить баги дальше в домене. 3. Idempotency Повторы запросов — нормальная история для любой сети. Idempotency-key или уникальный индекс часто спасают от дублей и лишних списаний. 4. Retry без фанатизма Бесконечные retry под нагрузкой легко добивают зависимый сервис — а заодно и ваш. Обычно хватает ограниченного числа попыток с backoff. Чем меньше домен знает о чужих форматах, тем спокойнее переживаются изменения во внешних системах.
193 ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
Ваш backend слишком сложный. Скорее всего — без причины. У большинства команд сложность растёт незаметно. Сначала “давайте сразу сделаем правильно”, потом появляются абстракции, фабрики, менеджеры менеджеров — и через полгода никто не понимает, как это работает. Плохая новость: сложность почти всегда дороже железа. Несколько тревожных сигналов: — Новый разработчик боится трогать код — Любое изменение требует правок в 5 слоях — Архитектуру нужно объяснять на созвоне — Без схемы в Miro ничего не ясно Частая причина — преждевременное масштабирование. Система ещё не испытывает нагрузку, а её уже проектируют как Netflix. Что обычно работает лучше: 1. Простые сервисы Если класс нельзя объяснить за 30 секунд — он почти наверняка перегружен. 2. Меньше “универсальных” решений Код, который “подойдёт на будущее”, часто не нужен вообще. 3. Оптимизация по фактам Сначала метрики → потом усложнение. Не наоборот. 4. Локальная понятность Открыл файл — понял, что происходит. Это underrated свойство хорошего backend-а. Интересный парадокс: сильные инженеры чаще упрощают систему, а не усложняют её. Иногда лучший архитектурный рефакторинг — это удаление половины кода.
162 ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
Как на самом деле работает отбор резюме в 2026 году Современный найм — это не «человек читает ваше резюме». Это нейронайм: автофильтры, парсеры и быстрые решения рекрутеров. Большинство кандидатов отсеиваются до того, как их резюме кто-то осознанно посмотрит. Базовые фильтры, о которых не говорят вслух - Опыт менее 3 лет в большинстве случаев автоматически ведёт к отказу. - Возраст ниже 25 лет часто не проходит первичную фильтрацию, даже если это нигде не написано. - Отсутствие ключевых слов в блоке навыков = отказ. Автопарсеры сопоставляют резюме с вакансией по совпадению терминов, а не по смыслу. Учебные практики и стажировки не считаются коммерческим опытом. Неайтишный бэкграунд не усиливает резюме айтишника — он его размывает. Что не стоит указывать в резюме ❌ Желаемый доход ❌ Личные соцсети ❌ Фотографию 🖥GitHub не всегда важен и редко смотрится на этапе фильтрации. Образование в большинстве случаев вообще не проверяется. Зато важно: 👉 указывать стек технологий отдельно для каждой компании, а не общим списком. Резюме — это продажа, а не автобиография Успешный программист умеет продавать себя. Продажи в найме бывают: - тупыми — «я хороший, возьмите меня» - умными — «я закрываю вашу боль» На HeadHunter обязательно используйте инструменты, которые повышают ваш статус в выдаче. Это напрямую влияет на количество просмотров. Не тратьте время на «подтверждение навыков». Лучше используйте репозиторий на GitHub как опору, а не как главный аргумент. Умная продажа — это: - правильное позиционирование, - попадание в запрос работодателя, - демонстрация пользы, а не личности. Как должно выглядеть сильное резюме Резюме — это рекламный буклет, а не отражение вашей души. Через него нужно донести: - умение общаться, - способность решать задачи, - ответственность за результат. Каждое место работы описывается по одному шаблону: Контекст — где и в каких условиях вы работали Достижения — что изменилось благодаря вам Стек — конкретные технологии Достижения оформляются
4 · 213 ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
«Какой навык самый важный для разработчика?» Ответ неожиданно простой — умение учиться быстрее других. В книге «The Only Skill That Matters» Джонатан Леви показывает: в мире, где технологии меняются каждые 2–3 года, выигрывает не самый умный и не самый опытный. Выигрывает тот, кто быстрее осваивает новое. Разберём идеи, которые особенно полезны нам — разработчикам. 🧠 1. Учёба — это навык, а не талант «У меня плохая память» — это не приговор. Память тренируется так же, как мышцы. Если вы можете выучить синтаксис нового фреймворка — вы уже тренируете её. 📚 2. Пассивное чтение = иллюзия прогресса Просто читать документацию — мало. Гораздо эффективнее: — писать мини-конспекты — формулировать вопросы к тексту — пересказывать материал своими словами — объяснять коллеге или близким Если не можешь объяснить ребенку — значит, не понял. ⏳ 3. Интервальные повторения > «зубрёжка» Повторять нужно не сразу, а через интервалы: 1 день → 3 дня → неделя → месяц Так знания переходят в долгосрочную память. И да, это работает лучше, чем «перед дедлайном всё перечитать». 🎯 4. Сначала структура, потом детали Не нужно запоминать всё подряд. Сначала разберитесь: — какая архитектурная идея стоит за технологией — какие 20% дают 80% понимания — какие основные сущности и связи После этого детали ложатся сами. 🔥 5. Фокус — множитель скорости Мультизадачность = медленное обучение. Если изучаете новый инструмент: — закройте Telegram — уберите уведомления — выделите 40–60 минут глубокой концентрации Один час глубокого фокуса = 3 часа «в фоновом режиме». 🎓 6. Учись через преподавание Самый быстрый способ разобраться в сложной теме — написать о ней пост. Или объяснить её стажёру. Или записать короткое видео. Объяснение структурирует знания лучше любого конспекта. ——————— В 2026 году побеждает не тот, кто знает больше. Побеждает тот, кто быстрее освоит: — новый паттерн — новую библиотеку — новый стек — новую архитектуру или 1с🤣 Самый ценный навык разработчика — скорость адап
5 · 272 ·
P
PYTHON IN DEPTH🐍
Foto
haz clic para mostrar
«Пузырь лопнул», «айти всё», «рынок умер» — каждый раз читаем это с новым интересом. Но давайте без лишних эмоций. Факты такие: — массового “схлопывания” рынка нет. — но перегретого найма 2021–2022 тоже больше нет. — зарплаты растут медленнее инфляции. — конкуренция среди джунов выше. — компании стали осторожнее. Бизнес — это борьба за ресурсы. Разработчик — это ресурс. Если вы понимаете это — половина тревожных постов перестаёт действовать. Когда аутсорс-компания пишет «рынок сложный, зарплаты падают, берите что дают» — это не аналитика. Это позиция покупателя на переговорах. Им выгодно, чтобы вы верили, что: — работы мало — альтернатив нет — нужно соглашаться быстрее Те, у кого входящий поток предложений, просто идут дальше. Те, кто сомневается — начинают демпинговать сами себя. Это обычная стратегия закупки. В IT разная реальность: • в стартапе разработчик — это расход до момента масштабирования • в крупной компании — это генератор огромной добавленной стоимости Отсюда и разница в ощущениях «рынок плохой» / «работы полно». Не каждый бизнес хочет «побеждать рынок». Некоторые модели работают на минимальных расходах и живут за счёт экономии. Им выгодны дешёвые специалисты. Им выгодна паника. Поэтому вопрос всегда один: Кто это пишет и чьи интересы стоят за сообщением? За последние годы рынок стал более зрелым и спокойным. Но сезонность, циклы и спрос никуда не делись. Айти не умерло! Оно просто перестало быть лёгким. А лёгкое — заканчивается всегда. Работать нужно лучше. Позиционироваться — умнее. И не читать аналитику от тех, кто покупает ваш труд. Спокойствие — тоже конкурентное преимущество.
343 ·
PYTHON IN DEPTH🐍
Без маркетинга: GPT-1 — 248 дней GPT-2 — 469 дней GPT-3 — 1020 дней GPT-4 — 877 дней GPT-5 — 392 дней GPT-6 — ....
50 ·
P
GPT-1 — прожил 248 дней GPT-2 — прожил 469 дней GPT-3 — прожил 916 дней GPT-3.5 — прожил 104 дня GPT-4 — прожил 237 дней GPT-4 Turbo — прожил 189 дней GPT-4o — прожил 290 дней GPT-4.5 — прожил 46 дней GPT-4.1 — прожил 115 дней GPT-5 — прожил 97 дней GPT-5.1 — прожил 29 дней GPT-5.2 — прожил 84 дня GPT-5.4 — прожил 49 дней GPT-5.5 — прожил 77 дней GPT-5.6 — прожил 56 дней GPT-6 Astra — прожил 19 дней GPT-6 Sol — прожил 7 дней GPT-6.1 Sol — только родился, 5 дней Даёшь новый AGI на каждое моргание!
1 · 49 ·

Un feed público abierto del índice de búsqueda ChatCrawler — el “Google del Telegram público”; se actualiza a medida que se rastrea la comunidad. Las horas se muestran en UTC.

Solo contenido público, API oficial de Telegram. Acerca de · Preguntas frecuentes · Límites del índice · Eliminar una página · Catálogo · Búsqueda · Cómo contamos