Ачааллж байна...
Өмнөх хичээлд бид @dataclass -ын үндсийг үзсэн: тэр нь __init__, __repr__, __eq__ -ыг автоматаар үүсгэдэг, frozen=True нь immutable болгож __hash__ нэмдэг.
Одоо түүнийг ЖИНХЭНЭ ПРАКТИКТ ашиглах чадвар руу орно. Гурван зүйл сурна:
Default утга — Бүлэг 3.1-ийн мэдлэг class дээр ажиллана
field() — mutable default-ын урхийг шийдэх зам
field(init=False) — тооцоологдсон талбарууд
Мөн энэ хичээлийн төгсгөлд би нэг зүйлийг чангаар хэлнэ, тэр нь энэ бүлгийн — магадгүй бүх курсийн — хамгийн чухал ажиглалт байх болно.
Бүлэг 3.1-ээс default параметрийг санаж байгаа байх: "хэрэв дуудагч утга өгөөгүй бол, энэ утгыг ашигла."
Dataclass-д тэр нь ЯГ ижилхэн ажиллана — зөвхөн бичлэг нь class-ын түвшинд байна.
python
from dataclasses import dataclass
@dataclass
class Zarlaga:
ner: str
dun: int
angilal: str = "бусад"
tailbar: str = ""
z1 = Zarlaga("Ном", 15000, "боловсрол", "Хичээлд хэрэгтэй")
z2 = Zarlaga("Автобус", 1000, "тээвэр")
z3 = Zarlaga("Тодорхойгүй", 5000)
print(z1)
print(z2)
print(z3)Zarlaga(ner='Ном', dun=15000, angilal='боловсрол', tailbar='Хичээлд хэрэгтэй')
Zarlaga(ner='Автобус', dun=1000, angilal='тээвэр', tailbar='')
Zarlaga(ner='Тодорхойгүй', dun=5000, angilal='бусад', tailbar='')Бичлэгийг задалъя:
python
angilal: str = "бусад"Гурван хэсэг: нэр, цэгтэй таслал, төрөл, тэнцүү тэмдэг, default утга. Яг Бүлэг 4.4-т үзсэн бичлэг.
Тэгэхээр Zarlaga -г үүсгэхэд angilal ба tailbar нь СОНГОЛТТОЙ болсон.
Хатуу дүрэм ажиллаж байна: default-гүй талбарууд ЭХЭНД, default-тай нь араас. Бүлэг 3.1-ээс танил дүрэм.
Хэрэв зөрчвөл:
python
@dataclass
class Zarlaga:
ner: str = "Тодорхойгүй"
dun: int # default-гүй, default-тайгийн АРД!Traceback (most recent call last):
File "main.py", line 4, in <module>
class Zarlaga:
TypeError: non-default argument 'dun' follows default argumentnon-default argument 'dun' follows default argument — "default утгагүй аргумент нь default утгатайгийн ард орсон байна."
Яг ижил алдаа, Бүлэг 3.1-т функц дээр харсан. Учир нь dataclass нь эцэст нь __init__ функц үүсгэж байгаа тул тэр функцийн дүрэм хэвээрээ ажиллана.
Бүлэг 3.2-ын keyword argument нь энд ч ажиллана:
python
z = Zarlaga(ner="Ном", dun=15000, angilal="боловсрол")
print(z)Zarlaga(ner='Ном', dun=15000, angilal='боловсрол', tailbar='')Мөн дунд байгаа талбарыг алгасаж болно:
python
z = Zarlaga("Ном", 15000, tailbar="Чухал")
print(z)Zarlaga(ner='Ном', dun=15000, angilal='бусад', tailbar='Чухал')angilal -ыг алгаслаа, tailbar -ыг нэрээр нь өглөө. Бүлэг 3.2-ын БҮХ мэдлэг dataclass дээр шууд ажиллаж байна.
Практик зөвлөгөө: талбар олон бол keyword ашиглах нь илүү тод.
python
# Хэцүү уншигдана
z = Zarlaga("Ном", 15000, "боловсрол", "Чухал")
# Өөрөө тайлбарлаж байна
z = Zarlaga(
ner="Ном",
dun=15000,
angilal="боловсрол",
tailbar="Чухал",
)Одоо танил асуудал шинэ хэлбэрээр гарч ирнэ.
Номын сангийн гишүүн class бичье. Гишүүн бүр зээлсэн номнуудын жагсаалттай.
python
from dataclasses import dataclass
@dataclass
class Gishuun:
id: int
ner: str
zeeldsen_nomnuud: list[str] = []Traceback (most recent call last):
File "main.py", line 5, in <module>
class Gishuun:
File "main.py", line 8, in Gishuun
zeeldsen_nomnuud: list[str] = []
ValueError: mutable default <class 'list'> for field zeeldsen_nomnuud is not allowed: use default_factorymutable default <class 'list'> for field zeeldsen_nomnuud is not allowed: use default_factory гэдэг нь "list нь өөрчлөгддөг тул default утга болж болохгүй: default_factory ашигла" гэсэн үг.
Танил санагдаж байна уу?
Бүлэг 3.1-ийн mutable default trap -ыг санаж байна уу? Тэнд бид ийм код бичсэн:
python
def ajil_nemekh(ner, jagsaalt=[]): # УРХИ!
jagsaalt.append(ner)
return jagsaaltТэр код нь АЖИЛЛАСАН, гэхдээ БУРУУ ажилласан — бүх дуудалт НЭГ л жагсаалтыг хуваалцаж байсан. Python нь юу ч гэсэнгүй, зөвхөн чимээгүй буруу үр дүн өгсөн.
Одоо dataclass нь тэр урхийг ХОРИГЛОЖ байна.
Энэ бол ГАЙХАЛТАЙ зүйл. Python-ы бүтээгчид тэр урхийг мэддэг, тэд түүнийг функц дээр засаж чадаагүй (хуучин код эвдэрнэ), гэхдээ dataclass нь шинэ тул тэнд ЭХНЭЭС НЬ хориглосон.
Хэрэв тэр хориг байхгүй байсан бол юу болох байсан бэ?
python
# ТӨСӨӨЛӨЛ — Python үүнийг зөвшөөрдөггүй
g1 = Gishuun(1001, "Болд")
g2 = Gishuun(1002, "Сараа")
g1.zeeldsen_nomnuud.append("Монголын нууц товчоо")
print(g2.zeeldsen_nomnuud) # ХОЁР ДАХЬ гишүүн!['Монголын нууц товчоо'] # СараA-д Болдын ном харагдаж байна!Хоёр өөр гишүүн НЭГ л жагсаалтыг хуваалцах байсан. Болд ном зээлэхэд Сараагийн жагсаалтад ч гарч ирэх байсан. Аймшигтай алдаа, мөн олоход маш хэцүү.
Тиймээс Python нь түүнийг ХОРИГЛОЖ байна. Талархалтай байя.
field(default_factory=...)python
from dataclasses import dataclass, field
@dataclass
class Gishuun:
id: int
ner: str
zeeldsen_nomnuud: list[str] = field(default_factory=list)
g1 = Gishuun(1001, "Болд")
g2 = Gishuun(1002, "Сараа")
g1.zeeldsen_nomnuud.append("Монголын нууц товчоо")
print(g1)
print(g2)Gishuun(id=1001, ner='Болд', zeeldsen_nomnuud=['Монголын нууц товчоо'])
Gishuun(id=1002, ner='Сараа', zeeldsen_nomnuud=[])ЗӨВ. Гишүүн бүр өөрийн ТУСДАА жагсаалттай.
field(default_factory=list) -ыг задалъя.
field нь dataclasses -аас import хийгддэг функц. Тэр нь талбарт нэмэлт заавар өгөх боломж олгодог.
default_factory=list гэдэг нь: "default утга хэрэгтэй болбол — list функцийг ДУУДАЖ, шинэ жагсаалт үүсгэ."
Хамгийн чухал нарийвчлал: list гэж хаалтгүй бичсэн. list() ГЭЖ БИЧЭЭГҮЙ.
Яагаад? Бүлэг 3.5-ын сургамжийг санаж байна уу — "хаалт бүх ялгааг үүсгэдэг"?
list — функц ӨӨРӨӨ (жорын цаас)
list() — функцийн ДУУДАЛТ, хоосон жагсаалт буцаана (бэлэн хоол)
default_factory нь функц хүлээж байна, жагсаалт биш. Тэр нь тэр функцийг объект үүсэх БҮРД дуудна. Ингэснээр объект бүр ШИНЭ жагсаалт авна.
Бүлэг 3.5-ын "функц бол утга" гэсэн санаа энд бодит ажилд орж байна. Та функцийг дамжуулж байна, түүний үр дүнг биш.
Бүлэг 3.1-ийн шийдэлтэй харьцуулъя:
python
# Бүлэг 3.1 — функц дээр
def ajil_nemekh(ner: str, jagsaalt: list[str] | None = None) -> list[str]:
if jagsaalt is None:
jagsaalt = [] # ГАРААР үүсгэнэ
jagsaalt.append(ner)
return jagsaalt
# Бүлэг 9.2 — dataclass дээр
@dataclass
class Gishuun:
zeeldsen_nomnuud: list[str] = field(default_factory=list) # АВТОМАТААРИжил асуудал, ижил шийдэл, өөр хэлбэр. Dataclass нь if x is None шалгалтыг таны өмнөөс хийж байна.
default_factory нь ямар ч аргументгүй функц хүлээж авна.
python
from dataclasses import dataclass, field
@dataclass
class Tokhirgoo:
neres: list[str] = field(default_factory=list) # хоосон жагсаалт
tootsuud: dict[str, int] = field(default_factory=dict) # хоосон dictionary
tagууd: set[str] = field(default_factory=set) # хоосон set
t = Tokhirgoo()
print(t)Tokhirgoo(neres=[], tootsuud={}, tagууd=set())list, dict, set — гурвуулаа хаалтгүй.
Мөн өөрийн функц ашиглаж болно:
python
from dataclasses import dataclass, field
from datetime import date
def odoogiin_ognoo() -> str:
return date.today().isoformat()
@dataclass
class Zarlaga:
ner: str
dun: int
ognoo: str = field(default_factory=odoogiin_ognoo)
z = Zarlaga("Ном", 15000)
print(z)Zarlaga(ner='Ном', dun=15000, ognoo='2026-07-13')Огноо нь объект үүсэх БҮРД шинээр тооцоологдоно.
Хэрэв бид ognoo: str = odoogiin_ognoo() гэж бичсэн бол (хаалттай!) — тэр нь ПРОГРАММ ЭХЛЭХ үед НЭГ УДАА тооцоологдож, бүх объект ижил огноотой болох байсан. Программ хэдэн өдөр ажиллавал — бүх зарлага эхний өдрийн огноотой байх байсан.
Дахин: хаалт бүх ялгааг үүсгэдэг.
Бүлэг 6.1-ээс санаж байгаа байх: JSON-д огноо байхгүй тул string болгож хадгална. date.today().isoformat() нь "2026-07-13" гэсэн string өгдөг — яг л JSON-д тохирсон хэлбэр.
field(init=False) — тооцоологдсон талбарЗаримдаа талбар нь бусад талбараас ТООЦООЛОГДДОГ бөгөөд түүнийг гаднаас өгөх шаардлагагүй байдаг.
python
from dataclasses import dataclass, field
@dataclass
class Zarlaga:
ner: str
dun: int
tatvariin_khuvi: float = 0.1
niit: int = field(init=False)
def __post_init__(self) -> None:
self.niit = self.dun + int(self.dun * self.tatvariin_khuvi)
z = Zarlaga("Ном", 15000)
print(z)
print(z.niit)Zarlaga(ner='Ном', dun=15000, tatvariin_khuvi=0.1, niit=16500)
16500Хоёр шинэ зүйл гарч ирлээ.
field(init=False) гэдэг нь: "энэ талбарыг __init__ -д БҮҮ оруул." Тэгэхээр Zarlaga("Ном", 15000) гэж дуудахад niit -ийг өгөх шаардлагагүй.
__post_init__ гэдэг нь special method — __init__ дууссаны ДАРАА автоматаар дуудагддаг. Тэнд та тооцоолол хийж болно.
Нэрийг анзаараарай: post = "дараа". Тэр нь __init__ -ийн дараа ажиллана, тиймээс бүх талбарууд бэлэн болсон байна.
Гэхдээ энд ЧУХАЛ асуулт байна: энэ зөв шийдэл үү?
Бүлэг 8.4-ийн property -ийн сургамжийг санаж байна уу?
"Хэрэв утга нь өөр талбаруудаас ТООЦООЛОГДДОГ бол — түүнийг ХАДГАЛЖ БОЛОХГҮЙ. Property болго."
Дээрх кодод niit нь ХАДГАЛАГДСАН. Тэгэхээр:
python
z = Zarlaga("Ном", 15000)
print(z.niit)
z.dun = 30000
print(z.niit) # шинэчлэгдэх үү?16500
16500ХУУЧРАЛАА. Яг л Бүлэг 8.4-ийн асуудал.
Зөв шийдэл: property.
python
from dataclasses import dataclass
@dataclass
class Zarlaga:
ner: str
dun: int
tatvariin_khuvi: float = 0.1
@property
def niit(self) -> int:
return self.dun + int(self.dun * self.tatvariin_khuvi)
z = Zarlaga("Ном", 15000)
print(z.niit)
z.dun = 30000
print(z.niit)16500
33000ҮРГЭЛЖ ШИНЭХЭН.
Property нь дуудагдах бүрд дахин тооцоолж байна. Хэзээ ч хуучрахгүй.
Мөн код нь БОГИНО: field(init=False) ба __post_init__ хэрэггүй.
Тэгвэл __post_init__ хэзээ хэрэгтэй вэ?
Хоёр тохиолдолд:
1. ШАЛГАЛТ хийх.
python
from dataclasses import dataclass
@dataclass(frozen=True)
class Zarlaga:
ner: str
dun: int
angilal: str = "бусад"
def __post_init__(self) -> None:
if not self.ner.strip():
raise ValueError("Нэр хоосон байж болохгүй")
if self.dun <= 0:
raise ValueError(f"Дүн эерэг байх ёстой, {self.dun} ирлээ")
z1 = Zarlaga("Ном", 15000)
print(z1)
z2 = Zarlaga("", 15000)Zarlaga(ner='Ном', dun=15000, angilal='бусад')
Traceback (most recent call last):
...
ValueError: Нэр хоосон байж болохгүйБуруу объект ОГТ ҮҮСЭХГҮЙ.
Энэ бол маш хүчирхэг санаа. Бүлэг 6.4-т бид "цэвэрлэх функц" бичсэн бөгөөд тэр нь None буцааж байсан. Одоо class ӨӨРӨӨ өөрийгөө хамгаалж байна.
Дүрэм: хүчингүй төлөвтэй объект оршин байх ЁСГҮЙ. Хэрэв өгөгдөл нь буруу бол — объект үүсэх ёсгүй.
2. Хүнд, УДААН тооцоолол.
Хэрэв тооцоолол нь удаан бол (жишээ нь файл унших, интернэтээс татах) — түүнийг property болгох нь МУУ. Учир нь z.niit гэж бичих бүрд секунд шаардах ажил хийгдэнэ.
Тэр үед __post_init__ -д НЭГ УДАА тооцоолж хадгалах нь зөв. Гэхдээ энэ нь ХОВОР тохиолдол.
Практик дүрэм:
Тооцоолол нь ХУРДАН → property
Тооцоолол нь УДААН → field(init=False) + __post_init__
ШАЛГАЛТ → __post_init__
Заримдаа талбарыг __repr__ -д харуулахыг хүсэхгүй байдаг.
python
from dataclasses import dataclass, field
@dataclass
class Kheregleagch:
ner: str
email: str
nuuts_ug_hash: str = field(repr=False)
kh = Kheregleagch("Болд", "bold@жишээ.mn", "a8f5f167f44f4964e6c998dee827110c")
print(kh)Kheregleagch(ner='Болд', email='bold@жишээ.mn')Нууц үгийн hash нь ХАРАГДАХГҮЙ.
Яагаад чухал вэ? Учир нь __repr__ нь ХАА САЙГҮЙ гарч ирдэг — дебаг хийхэд, лог бичихэд, алдааны мессежид. Хэрэв нууц мэдээлэл тэнд байвал — тэр нь лог файлд, дэлгэц дээр, магадгүй интернэтэд алдагдаж болно.
repr=False нь тэр эрсдэлийг арилгана.
Практик зөвлөгөө: нууц үг, API түлхүүр, токен — эдгээрийг repr=False -ээр нуу. Энэ бол мэргэжлийн аюулгүй байдлын зуршил.
python
field(default=утга) # энгийн default (эсвэл шууд = утга гэж бич)
field(default_factory=функц) # mutable default — list, dict, set
field(init=False) # __init__ -д БҮҮ оруул
field(repr=False) # __repr__ -д БҮҮ харуул
field(compare=False) # __eq__ -д БҮҮ оруулСүүлчийнх нь сонирхолтой. Бүлэг 8.2-ын сургамжийг санаж байна уу?
"
__eq__-д зөвхөн ОНОШ тодорхойлдог талбаруудыг л оруул. ТӨЛӨВ -ийг бүү оруул."
compare=False нь яг тэр:
python
from dataclasses import dataclass, field
@dataclass
class Nom:
isbn: str
garchig: str
zeeldsen: bool = field(default=False, compare=False)
n1 = Nom("978-1", "Монголын нууц товчоо", zeeldsen=False)
n2 = Nom("978-1", "Монголын нууц товчоо", zeeldsen=True)
print(n1 == n2)TrueНэг нь зээлэгдсэн, нөгөө нь үгүй. Гэвч ТЭНЦҮҮ — учир нь zeeldsen нь харьцуулалтаас хасагдсан.
Яг Бүлэг 8.2-ын жишээ, гэхдээ нэг keyword-ээр шийдэгдлээ. Гараар __eq__ бичих шаардлагагүй.
Одоо би нэг зүйлийг чангаар хэлье. Энэ бол энэ бүлгийн, магадгүй бүх курсийн хамгийн чухал өгүүлбэр байх болно.
Дараах кодыг хараарай:
python
from dataclasses import dataclass
@dataclass
class Zarlaga:
ner: str
dun: int
angilal: str = "бусад"
tailbar: str | None = NoneЭнэ бүтцийг САЙН хараарай. Тэнд ГУРВАН зүйл нийлж байна:
Class — өгөгдлийн бүтэц
Type hint — талбар бүрийн төрөл
Default утга — сонголттой талбарууд
Одоо FastAPI-гийн жинхэнэ documentation-оос авсан кодыг хараарай:
python
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
description: str | None = None
tax: float = 0.0БАРАГ ЯГ ИЖИЛ.
@dataclass -ын оронд BaseModel -ээс өвлөж байна. Гэхдээ БҮТЭЦ нь яг ижилхэн: class, type hint, default утга.
Pydantic гэдэг нь FastAPI-гийн ашигладаг сан бөгөөд тэр нь dataclass-тай ижил зарчмаар ажилладаг: type hint-ийг уншиж, түүн дээр үндэслэн бүх зүйлийг автоматаар бүтээдэг.
Гэхдээ Pydantic нь илүү холдоно. Тэр нь:
Ирж байгаа өгөгдлийг АВТОМАТААР ШАЛГАНА (price нь тоо биш бол алдаа буцаана)
Өгөгдлийг АВТОМАТААР ХӨРВҮҮЛНЭ ("15000" string ирвэл 15000 int болгоно)
JSON руу, JSON-оос АВТОМАТААР хөрвүүлнэ
АВТОМАТААР БАРИМТ БИЧИГ ҮҮСГЭНЭ
Тэр бүхэн ЗӨВХӨН таны бичсэн type hint дээр үндэслэнэ.
Тэгэхээр:
Бүлэг 4-т та type hint сурсан. Бүлэг 8-д та special method сурсан. Бүлэг 9-д та dataclass сурлаа. Эдгээр гурав нийлж — Pydantic-ийн БҮТЭЦ болно. Тэр нь FastAPI-гийн ЗҮРХ юм.
Бүлэг 15-д та FastAPI программ бичихэд яг ийм class бичнэ. Тэгээд /docs хуудсыг нээхэд — таны бичсэн type hint-үүдээс АВТОМАТААР үүссэн, интерактив баримт бичиг харагдана.
Тэр мөч илбэ мэт санагдана. Гэвч та одоо түүний ард ЮУ байгааг мэдэж байна.
@dataclass нь type hint уншиж, __init__ үүсгэдэг. Pydantic нь type hint уншиж, шалгалт үүсгэдэг. FastAPI нь type hint уншиж, баримт бичиг үүсгэдэг.
Нэг л зарчим, гурван түвшин. Та түүнийг эндээс, dataclass-аас эхлэн ойлголоо.
Хэрэв сонирхвол: Gishuun class-д field(default_factory=list) -ийн оронд = [] гэж бичээд, ValueError -ыг өөрийн нүдээр хараарай. Дараа нь зөв болгоод, хоёр гишүүн үүсгэж, нэгэнд нь ном нэмээд, нөгөө нь ХӨНДӨГДӨӨГҮЙ гэдгийг батлаарай.
Дараа нь __post_init__ -д шалгалт нэмээд, буруу утгатай объект үүсгэж оролдоод, ValueError -ыг хараарай. Хүчингүй объект оршин байж чадахгүй — тэр мэдрэмж нь маш тайвшруулдаг.
Мөн хүсвэл: field(repr=False) -ээр нууц талбар үүсгээд, print(objekt) дуудаж, тэр талбар нуугдаж байгааг хараарай.
1. Mutable default -ыг шууд бичих
python
zeeldsen_nomnuud: list[str] = []ValueError: mutable default <class 'list'> for field zeeldsen_nomnuud is not allowed: use default_factoryЗасвар: field(default_factory=list).
2. default_factory -д ХААЛТ бичих
python
zeeldsen_nomnuud: list[str] = field(default_factory=list())TypeError: 'list' object is not callabledefault_factory нь функц хүлээж байна, түүний үр дүнг биш. Хаалтгүй: default_factory=list.
Бүлэг 3.5-ын сургамж: дамжуулахад хаалтгүй, дуудахад хаалттай.
3. field -ыг import мартах
python
from dataclasses import dataclass # field байхгүй!NameError: name 'field' is not definedЗасвар: from dataclasses import dataclass, field.
4. Default-гүй талбарыг default-тайгийн ард тавих
TypeError: non-default argument 'dun' follows default argumentБүлэг 3.1-ийн дүрэм: default-гүй нь ЭХЭНД.
5. Тооцоологдсон утгыг ХАДГАЛАХ
python
niit: int = field(init=False)
def __post_init__(self) -> None:
self.niit = self.dun * 1.1Ажиллана, гэхдээ dun өөрчлөгдөхөд niit нь ХУУЧРАНА. Property ашигла (хурдан тооцоолол бол).
6. Frozen class-д __post_init__ -ээр утга олгох
python
@dataclass(frozen=True)
class Zarlaga:
ner: str
dun: int
niit: int = field(init=False)
def __post_init__(self) -> None:
self.niit = self.dun * 2dataclasses.FrozenInstanceError: cannot assign to field 'niit'Frozen объект нь __post_init__ -д ч гэсэн өөрчлөгдөж чадахгүй. Засвар: property ашигла (энэ нь ямар ч тохиолдолд илүү зөв).
Default утга нь dataclass-д ердийн бичлэгээр: angilal: str = "бусад". Бүлэг 3.1, 3.2, 4.4-ийн БҮХ дүрэм хэвээрээ ажиллана.
Default-гүй талбарууд ЭХЭНД, default-тай нь араас → эс тэгвээс TypeError.
Mutable default (list, dict, set) нь ХОРИГЛОГДСОН → ValueError: use default_factory. Python нь Бүлэг 3.1-ийн урхийг эхнээс нь хааж байна.
field(default_factory=list) — объект үүсэх БҮРД шинэ жагсаалт үүсгэнэ. ХААЛТГҮЙ бич (list, list() биш) — функцийг дамжуулж байна.
field(init=False) + __post_init__ — __init__ -ийн ДАРАА ажиллах код.
__post_init__ -ыг ЗӨВХӨН хоёр зүйлд ашигла: (1) ШАЛГАЛТ (raise ValueError — хүчингүй объект ОГТ үүсэхгүй), (2) УДААН тооцоолол.
Хурдан тооцоолол → @property (Бүлэг 8.4). Тооцоологдсон утгыг ХАДГАЛБАЛ тэр нь ХУУЧРАНА.
field(repr=False) — нууц үг, API түлхүүрийг __repr__ -ээс нуу.
field(compare=False) — төлөв талбарыг __eq__ -ээс хас (Бүлэг 8.2-ын санаа, нэг keyword-ээр).
ХАМГИЙН ЧУХАЛ: dataclass + type hint + default утга = ЯГ ТЭР бүтэц, Pydantic ашигладаг. Pydantic бол FastAPI-гийн зүрх. Бүлэг 15-д та яг ийм class бичих бөгөөд FastAPI нь түүнээс автоматаар шалгалт, хөрвүүлэлт, баримт бичиг үүсгэнэ.
Дараагийн хичээлд бид Бүлэг 9-ийн сүүлчийн ойлголтын хичээлийг үзнэ: dataclass ба JSON. Тэнд бид Бүлэг 6-ийн мэдлэгийг dataclass-тай холбоно — объектыг JSON болгож хадгалах, JSON-оос объект сэргээх. Тэр нь Бүлэг 9-ийн guided build (номын сангийн систем) -ийн шууд бэлтгэл бөгөөд мөн Бүлэг 15-д FastAPI-гийн хийдэг зүйлийн ГАРААР хийсэн хувилбар юм.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.