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
№ 205
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
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