tg-me.com/hw_code/593
Last Update:
Дрочим датаклассы 💅🏻
Долго мучился с вопросом, что делать с длинными постами. Не вижу смысла писать короткие примеры типа "почему плохо совать [] в дефолтный аргумент в функции". За годы тут я выработал отвращение к повторяющимся скучным постам в блогах, бесконечным вопросам в комментах вроде "бро, контент будет? или снова репост старого поста?" и т.д. Хорошо, что в тг теперь можно использовать нормальный inline code markdown. Поэтому здесь я заканчиваю предисловие, и мы начинаем.
Зачем нужны датаклассы?
Базовая фишка датаклассов - красивое представление объекта при выводе через print
. Например, класс User
:
class User:
def __init__(self, user_id: int, name: str) -> None:
self.user_id = user_id
self.name = name
user = User(user_id=1111, name="@hw_code")
print(user)
на экран вылезет что-то в духе:
<__main__.User object at 0x0000021492214BD0>
Таким образом, нет необходимости писать самостоятельно
__repr__
или __str__
(ну, по сути __repr__
, это легко проверить, если его перегрузить).Создание датакласса.
При создании датакласса стоит отметить следующую вещь. Датаклассы в каком-то смысле абузят понятие классовой переменной (это которая обычно общая для всех инстансов), также добавляя необходимые нам классовые методы сравнения, и прочего.
from dataclasses import dataclass
@dataclass
class User:
user_id: int
name: str
Очевидно, что они потом добавляются в
__init__
, следовательно данная запись аналогична предыдущей. Но теперь при вызове print
мы увидим что отрабатывает дефолтный __repr__
датакласса.Основные моменты.
Теперь кратко обсудим основные моменты. Можно добавлять дефолтные значения:
@dataclass
class User:
user_id: int
name: str
is_active: bool = True
работает так только для простых типов. Для сложных вроде списков нам понадобится
field
и default_factory
:@dataclass
class User:
user_id: int
name: str
is_active: bool = True
email_addresses: list[str] = field(default_factory=list)
поскольку мы хотим каждый раз создавать новый список, мы указываем функцию, которая будет создавать нам этот список. Если например мы захотим чтобы у каждого нового юзера автоматически создавался айди, мы снова вернемся к
default_factory
, но укажем внутри функцию, которая создаст нам этот айди:import random
def my_super_ultra_id_func() -> int:
return random.randint(0, 1000)
@dataclass
class User:
user_id: int = field(default_factory=my_super_ultra_id_func)
name: str = field(default="")
is_active: bool = True
email_addresses: list[str] = field(default_factory=list)
ну и к имени тоже заодно докинул. Теперь например можно исключить список адресов из
__repr__
, если мы не хотим показывать это пользователю (читай прикладному программисту, юзающему наш класс).@dataclass
class User:
user_id: int = field(default_factory=my_super_ultra_id_func)
name: str = field(default="")
is_active: bool = True
email_addresses: list[str] = field(default_factory=list, repr=False)
Вывод с экрана:
User(user_id=498, name='hw_code', is_active=True)
Мы все еще можем использовать кастомные значения для параметров, указанных в аргументах:
user = User(user_id=1, name="hw_code", is_active=False, email_addresses=["[email protected]"])
print(user)
Вывод:
User(user_id=1, name='hw_code', is_active=False)
Не буду сильно затягивать здесь. Если статьи не читают из-за их длины, то и длинные посты, возможно, читают с меньшим желанием. Предлагаю вам здесь навалить лойсов, и тогда ваши билды всегда будут успешными, 10 раз смерджитесь в мастер, а сеньор вам руку пожмет. Ну или сами себе руку пожмете, фигурально, как в том меме с Обамой. А я отчаливаю, но возможно, выложу и вторую версию. Посмотрим.
@hw_code
BY Hello World
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/hw_code/593