TG Telegram Group & Channel
Библиотека Python разработчика | Книги по питону | United States America (US)
Create: Update:

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

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
👍8😎2


>>Click here to continue<<

Библиотека Python разработчика | Книги по питону




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)