11 Sep, 17:08
29 Aug, 14:26
29 Aug, 14:25
28 Aug, 21:11
15 Aug, 09:29
13 Aug, 08:41
class A:
pass
class B:
value = 1
class C:
value = 3
class D(A, B, C):
def __str__(self):
return str(self.value)
print(D())
D
наследуется от A
, B
и C
. Но когда мы печатаем D()
, атрибут value
берётся из класса B
! Почему?value
в классе D
.A
, но A
не имеет value
.B
— и находит value = 1
.B
стоит перед C
в MRO, используется value
из B
, поэтому вывод будет 1
! ⚙️D.mro()
:
[<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
08 Aug, 14:15
30 Jul, 14:27
23 Feb, 19:35
31 Dec, 21:02
18 Dec, 10:01
class User:
cvar: float = 0.5
def __init__(self, user_id: int, name: str) -> None:
self.user_id = user_id
self.name = name
from typing import ClassVar
@dataclass
class User:
cvar: ClassVar[float] = 0.5
user_id: int = field(default_factory=my_super_ultra_id_func)
name: str = field(default="")
user_id
и для name
, поскольку именованый cvar
должен был бы по идее идти после них, но я оставил его в начале.typing
наверняка все знакомы, если на норм проектах пишете... Как я и говорил, датаклассы абузят понятие классовой переменной, и базовый синтаксис в классах, но зато взамен вы получаете множество уже реализованных "под капотом" методов для работы с данными. В целом, справедливый обмен. Если остались какие то вопросы, в доке все довольно хорошо объяснено, и всегда можно заглянуть туда.17 Dec, 19:53
__init__
, __repr__
, etc.__init__
user_id
, который нам должен генерироваться автоматически. Для этого в аргумент добавим init=False
.
import random
def my_super_ultra_id_func() -> int:
return random.randint(0, 1000)
@dataclass
class User:
user_id: int = field(init=False, default_factory=my_super_ultra_id_func)
name: str = field(default="")
is_active: bool = True
email_addresses: list[str] = field(default_factory=list)
__post_init__
для создания полей__post_init__
.
@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)
search_string: str = field(init=False)
def __post_init__(self) -> None:
self.search_string = f"{self.user_id}: {self.name}"
user = User(user_id=1, name="hw_code", is_active=False, email_addresses=["[email protected]"])
User(user_id=1, name='hw_code', is_active=False, search_string='1: hw_code')
_search_string: str = field(init=False)
@dataclass
, значение аргумента frozen
в нем равно False
. Чтобы сделать "заморозить" поля датакласса, меняем это значение на True
.
@dataclass(frozen=True)
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)
search_string: str = field(init=False)
def __post_init__(self) -> None:
self.search_string = f"{self.user_id}: {self.name}"
user = User(user_id=1, name="hw_code", is_active=False, email_addresses=["[email protected]"])
user.name = "Big Dick" # ошибка
kw_only
аргумент
@dataclass(kw_only=True)
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)
search_string: str = field(init=False)
def __post_init__(self) -> None:
self.search_string = f"{self.user_id}: {self.name}"
# сработает
user = User(user_id=1, name="hw_code", is_active=False, email_addresses=["[email protected]"])
# не сработает
user = User(1, "hw_code", False, ["[email protected]"])
13 Dec, 19:04
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)
22 Aug, 11:25