Public channel ID 68567957048035

Python Разработка | Web Backend, Парсинг & Telegram Bots. Пайтон программирование с нуля. Django, FastAPI и SQL. Уроки для начинающих и IT карьера. Coding.

Реклама Tg t.me/evgenycarter

Учим язык Python на практике. Создание веб-приложений: Django, Flask, FastAPI. Пишем ботов для Телеграм на Aiogram. Парсинг сайтов (Web Scraping): Selenium, BeautifulSoup (BS4), Scrapy. Работа с базами данных (PostgreSQL, Redis, SQL) и API. Асинхронное программирование (Asyncio). Настройка Docker, Git и Linux. Алгоритмы, задачи с собеседований и Roadmap для Junior

Channels in category
7 559
This channel's rank
№ 204
Open category →
Channels in category
1 757
This channel's rank
№ 15
Open category →
Open in MAX

Posts for the period

By reactions

Search and the whole feed — after free registration. Custom dates — with a subscription; the channel owner sees them for free. Sorting by reactions — with a subscription. Sign up

Loading…

default_factory в dataclass: мощнее, чем кажется

Многие используют dataclass как удобный способ задать структуру с полями. Но редко кто по-настоящему раскрывает силу default_factory. А зря — он спасает от багов и даёт гибкость.

Когда нужно задать значение по умолчанию для поля в dataclass, логично тянуться к default=. Но если это изменяемый тип (например, список или словарь) — вас поджидает ловушка.

from dataclasses import dataclass, field

@dataclass
class User:
name: str
tags: list[str] = [] # ⚠️ опасно!


Все экземпляры User будут делить один и тот же список. То есть:

a = User("Alice")
b = User("Bob")
a.tags.append("admin")

print(b.tags) # ['admin'] 😱


Вместо этого используйте default_factory:

@dataclass
class User:
name: str
tags: list[str] = field(default_factory=list)


Теперь у каждого User будет свой список:

a = User("Alice")
b = User("Bob")
a.tags.append("admin")

print(b.tags) # []

Но default_factory не только про списки. Это отличный способ задать любое значение "по умолчанию", включая кастомную логику:

import uuid

@dataclass
class Session:
id: str = field(default_factory=lambda: str(uuid.uuid4()))
Или, например, значения из окружения:

import os

@dataclass
class Config:
debug: bool = field(default_factory=lambda: os.getenv("DEBUG") == "1")

Кстати, это ещё и отличное место для внедрения DI:

@dataclass
class Service:
client: "Client" = field(default_factory=create_default_client)

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

👉 @BookPython
Views: 505
Go to post Open in MAX Report an inaccuracy
Loading image…
🗄 Вебинар: JDBC: как Java-приложения взаимодействуют с базами данных
JDBC позволяет Java-приложениям работать с базами данных. Разберём подключение, SQL-запросы, транзакции и обработку ошибок.

💬 О чём поговорим
- Как подключиться к СУБД с помощью DriverManager и работать с Connection.
- Как выполнять SQL-запросы через Statement и PreparedStatement и получать результаты через ResultSet.
- Как управлять транзакциями: autocommit, commit и rollback.
- Как использовать SQLException, чтобы разобраться в причинах ошибки при выполнении запроса.

🎯 Результат урока:
- Вы разберётесь, как подключать Java-приложение к СУБД, выполнять SQL-запросы и работать с результатами.
- Узнаете, как управлять транзакциями и обрабатывать ошибки при обращении к базе данных.

👉 Для участия зарегистрируйтесь: https://vk.cc/d38Nyv

Вебинар проходит в рамках старта курса «Java-разработчик», который помогает освоить современную Java-разработку: от основ и первых программ до серверных приложений, баз данных, Spring, контейнеров и очередей сообщений. Программа регулярно обновляется под требования рынка. 🚀

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

Ad post

Views: 551
Go to post Open in MAX Report an inaccuracy
yield from — элегантная передача управления

Если вы пишете генераторы, которые вызывают другие генераторы — забудьте про for x in sub(): yield x. Есть способ проще и мощнее.

Оператор yield from позволяет передавать элементы из подгенератора напрямую, без лишнего кода. Но фишка не только в лаконичности — он также автоматически пробрасывает исключения и возвращаемые значения из подгенератора.

Вот классика:

def gen():
for x in range(3):
yield x

def wrapper():
for x in gen():
yield x


Можно короче и лучше:

def wrapper():
yield from gen()


Но главное — yield from пробрасывает return-значение из подгенератора (начиная с Python 3.3):

def sub():
yield 1
yield 2
return 'done'

def main():
result = yield from sub()
print('Sub returned:', result)

for _ in main():
pass
# Выведет: Sub returned: done


А ещё через yield from можно проксировать значения внутрь генератора — например, в сопрограммах:

def delegator():
result = yield from coroutine()
print('coroutine done:', result)

def coroutine():
x = yield
y = yield
return x + y

g = delegator()
next(g) # Старт
next(g) # coroutine ждет x
g.send(10) # x = 10
print(g.send(20)) # y = 20 → return 30
# Выведет: coroutine done: 30


Итог: если вы пишете генераторы — освоение yield from даст вам лаконичный синтаксис, проброс return-значений, исключений и взаимодействие на новом уровне.

👉 @BookPython
Views: 583
Go to post Open in MAX Report an inaccuracy
Когда вы используете модуль multiprocessing, и в одном из процессов происходит исключение, оно передаётся в основную программу с помощью механизма сериализации (pickling). Исключение сериализуется, передаётся в другой процесс и там десериализуется обратно.

Однако сериализация исключений может быть непростой задачей. Исключение создаётся с любым количеством аргументов, которые сохраняются в атрибуте args. Эти же аргументы используются при десериализации для воссоздания объекта исключения.

Но это может не сработать так, как вы ожидаете, особенно если используется наследование. Посмотрите на пример:

import pickle

class TooMuchWeightError(Exception):
def __init__(self, weight):
super().__init__()
self._weight = weight

pickled = pickle.dumps(TooMuchWeightError(42))
pickle.loads(pickled)


Вызов TooMuchWeightError.__init__ приводит к вызову Exception.__init__, который устанавливает args как пустой кортеж. Этот пустой кортеж затем используется в качестве аргументов при десериализации, что, очевидно, приводит к ошибке:

TypeError: __init__() missing 1 required positional argument: 'weight'

Обходное решение — либо вообще не вызывать super().__init__() (что обычно считается плохой практикой при наследовании), либо передавать все аргументы явно в конструктор родительского класса:

class TooMuchWeightError(Exception):
def __init__(self, weight):
super().__init__(weight)
self._weight = weigh
t

👉 @BookPython
Views: 826
Go to post Open in MAX Report an inaccuracy
Функция map вызывает другую функцию для каждого элемента итерируемого объекта. Это значит, что функция должна принимать одно значение в качестве аргумента:

In : list(map(lambda x: x ** 2, [1, 2, 3]))
Out: [1, 4, 9]


Однако если каждый элемент итерируемого объекта — это кортеж, было бы удобно передавать каждый элемент кортежа как отдельный аргумент. В Python 2 это было возможно благодаря распаковке параметров кортежа (обратите внимание на скобки):

>>> map(lambda (a, b): a + b, [(1, 2), (3, 4)])
[3, 7]


В Python 3 эта возможность исчезла, но есть другое решение — itertools.starmap. Она распаковывает кортежи за вас, будто функция вызывается со звёздочкой: f(*arg) (отсюда и название функции):

from itertools import starmap

In [3]: list(starmap(lambda a, b: a + b, [(1, 2), (3, 4)]))
Out[3]: [3, 7]


👉 @BookPython
Views: 919
Go to post Open in MAX Report an inaccuracy
Функция super() позволяет обращаться к родительскому (базовому) классу. Это может быть очень полезно в случаях, когда производный класс хочет добавить что-то к реализации метода, а не полностью переопределять его:

class BaseTestCase(TestCase):
def setUp(self):
self._db = create_db()

class UserTestCase(BaseTestCase):
def setUp(self):
super().setUp()
self._user = create_user()


Имя функции super не означает "отличный" или "очень хороший". В данном контексте слово super означает "выше" (как, например, в слове superintendent — заведующий). Несмотря на это, super() не всегда ссылается на базовый класс — он может вернуть и "соседний" класс. Более точным названием была бы, возможно, функция next(), так как возвращается следующий класс согласно цепочке разрешения методов (MRO — Method Resolution Order).

Пример:

class Top:
def foo(self):
return 'top'

class Left(Top):
def foo(self):
return super().foo()

class Right(Top):
def foo(self):
return 'right'

class Bottom(Left, Right):
pass

# выводит 'right'
print(Bottom().foo())


Обрати внимание: результат работы super() может отличаться в зависимости от MRO вызвавшего объекта.

>>> Bottom().foo()
'right'
>>> Left().foo()
'top'


👉 @BookPython
Views: 1 166
Go to post Open in MAX Report an inaccuracy
Стандартный механизм расширения путей в оболочке называется globbing. Шаблоны, которые вы используете для сопоставления путей, называются globs.

$ echo /li*
/lib /lib64


Python поддерживает globbing с помощью модуля glob. Однако есть важное замечание: оболочка возвращает сам шаблон, если файлы не найдены, а Python — нет:

$ echo /zz**
/zz**
$ python -c 'from glob import glob; print(glob("/zz**"))'
[]

👉 @BookPython
Views: 1 233
Go to post Open in MAX Report an inaccuracy
Обычно вы взаимодействуете с генератором, запрашивая данные с помощью next(gen). В Python 3 вы также можете отправлять значения обратно в генератор с помощью g.send(x). Но существует техника, которой вы, вероятно, не пользуетесь каждый день, а возможно, и вовсе не знаете: выбрасывание исключений внутри генератора.

С помощью gen.throw(e) можно выбросить исключение в той точке, где генератор gen приостановлен — то есть на инструкции yield. Если генератор обрабатывает это исключение, gen.throw(e) возвращает следующее значение, полученное через yield (или выбрасывает StopIteration, если генератор завершён). Если генератор не перехватывает исключение, оно пробрасывается обратно к вызывающему коду.

def gen():
try:
yield 1
except ValueError:
yield 2

g = gen()

next(g)
# Out: 1

g.throw(ValueError)
# Out: 2

g.throw(RuntimeError('TEST'))
# RuntimeError: TEST


Эта техника позволяет более точно управлять поведением генератора — не только передавать данные внутрь, но и, например, сообщать о проблемах со значениями, полученными через yield. Однако такие случаи бывают редко, и встретить g.throw в дикой природе почти невозможно.

Тем не менее, декоратор @contextmanager из модуля contextlib использует именно такую технику, позволяя коду внутри контекста перехватывать исключения.

from contextlib import contextmanager

@contextmanager
def atomic():
print('BEGIN')

try:
yield
except Exception:
print('ROLLBACK')
else:
print('COMMIT')

with atomic():
print('ERROR')
raise RuntimeError()
BEGIN
ERROR
ROLLBACK


👉 @BookPython
Views: 1 184
Go to post Open in MAX Report an inaccuracy
🚀 Подборка полезных IT каналов в Max


Системное администрирование, DevOps 📌

https://max.ru/i_odmin Все для системного администратора
https://max.ru/bash_srv Bash Советы
https://max.ru/sysadminof Книги для админов, полезные материалы
https://max.ru/i_odmin_book Библиотека Системного Администратора
https://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.
https://max.ru/tipsysdmin Типичный Сисадмин
https://max.ru/channel_win_sysadmin Системный Администратор Windows
https://max.ru/channel_linux_admin Linux: Системный администратор
https://max.ru/channel_linuxmod Linux
https://max.ru/channel_i_linux Системный администратор
https://max.ru/channel_devopslib DevOps, SRE, Sysadmin
https://max.ru/channel_devops_star DevOps Star (Звезда Девопса)

Excel лайфхак 📌
https://t.me/Excel_lifehack Excel лайфхак

Английский с нуля 🇬🇧
https://max.ru/UchuEnglish

1C разработка 📌
https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://max.ru/channel_DevLab1C 1С:Предприятие 8

Программирование C++📌
https://max.ru/cpp_lib Библиотека C/C++ разработчика
https://max.ru/channel_cpp_geek C++ geek

Программирование Go📌
https://max.ru/golang_lib Библиотека Go (Golang) разработчика

Программирование React📌
https://max.ru/react_lib React

Программирование Rust📌
https://max.ru/channel_rust_lib

Программирование Python 📌
https://max.ru/python_of Python академия.
https://max.ru/BookPython Библиотека Python разработчика

Java разработка 📌
https://max.ru/bookjava Библиотека Java разработчика
https://max.ru/channel_java_geek Java Geek

GitHub Сообщество 📌
https://max.ru/githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://max.ru/database_info Все про базы данных

Фронтенд разработка 📌
https://max.ru/frontend_1 Подборки для frontend разработчиков

Библиотеки 📌
https://max.ru/programmist_of Книги по программированию
https://max.ru/proglb Библиотека программиста
https://max.ru/bfbook Книги для программистов

Программирование 📌
https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференций
https://max.ru/itmozg Программисты, дизайнеры, новости из мира IT
https://max.ru/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻

Шутки программистов 📌
https://max.ru/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://max.ru/thehaking Канал о кибербезопасности
https://max.ru/xakkep_1 Хакер Free

Книги, статьи для дизайнеров 📌
https://max.ru/odesigners Статьи, книги для дизайнеров

Математика 📌
https://max.ru/Pomatematike Канал по математике
https://max.ru/phismat_1 Обучающие видео, книги по Физике и Математике

Вакансии в IT📌
https://max.ru/progjob
https://max.ru/channel_rabotait

Мир технологий 📌
https://max.ru/mir_teh Канал для любознательных

Городские📌
https://max.ru/piterspb_78 Свежие новости Санкт-Петербурга
https://max.ru/mockva_life Свежие новости Москвы
https://max.ru/piterspb Питер Новости: Санкт-Петербург / СПБ / ДТП
https://max.ru/channel_krasnodar_novosty Краснодар Новости
https://max.ru/channel_novosibirsk_novosti Новосибирск
https://max.ru/channel_samara_novosti Новости Самары
https://max.ru/channel_ekaterinburg_novosti Новости Екатеринбурга
https://max.ru/channel_kazan_novosti Новости Казани
https://max.ru/channel_omsk_novosti Новости Омска
https://max.ru/channel_moskva_24 Москва 24
Views: 1 134
Go to post Open in MAX Report an inaccuracy
Чтобы сохранить любую информацию в памяти или на устройстве хранения, её необходимо представить в виде байтов. Python, как правило, предоставляет уровень абстракции, при котором вы оперируете непосредственно данными, а не их байтовым представлением.

Тем не менее, когда вы, скажем, записываете строку в файл, вы работаете с физической структурой данных. Чтобы поместить символы в файл, их нужно преобразовать в байты — это называется кодированием. Когда вы получаете байты из файла, скорее всего, вы захотите превратить их в осмысленные символы — это называется декодированием.

Существует сотни методов кодирования. Самый популярный — вероятно, Unicode, но он сам по себе не может преобразовывать данные в байты. В смысле байтового представления Unicode вообще не является кодировкой. Unicode определяет соответствие между символами и их числовыми кодами. Например, 🐍 имеет код 128013.

Но чтобы записать числа в файл, нужна настоящая кодировка. Unicode обычно используется вместе с utf-8, которая (в большинстве случаев) является стандартной в Python. При чтении из файла Python автоматически декодирует utf-8. Вы можете выбрать любую другую кодировку с помощью параметра encoding= функции open, либо читать «сырые» байты, добавив b к режиму открытия файла.

👉 @BookPython
Views: 1 211
Go to post Open in MAX Report an inaccuracy
The full feed — after free sign-up
VKontakte Telegram Odnoklassniki
Favorites at datool.ru

Follow the channel in your account

Sign up at datool.ru to add the channel “Python Разработка | Web Backend, Парсинг & Telegram Bots. Пайтон программирование с нуля. Django, FastAPI и SQL. Уроки для начинающих и IT карьера. Coding.” to favorites and track its metrics.

Sign up
For channel owners

Verify your channel

Sign in or sign up at datool.ru, then add our bot to the channel following the instructions in your account. Once ownership is verified, the lock disappears and channel management becomes available.

Sign in or sign up

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go