6 min lexim
Tipat abstraktë të të dhënave
Çfarë bën kundrejt si e bën
Kur përdor një listë në Python, tashmë e mendon në dy mënyra të veçanta pa e vënë re. Ka atë që të lejon të bësh: shto një njësi, lexo njësinë në një pozicion, kërko gjatësinë. Dhe ka si e menaxhon atë prapa skene: ku ulen vlerat në memorie, si rritet kur mbushet. Shumicën e ditëve të intereson vetëm e para. Thërret .append() dhe i beson se punon; nuk e inspekton kurrë mekanizmin.
Kjo ndarje ka një emër. Një tip abstrakt i të dhënave (abstract data type, ose ADT) është një përshkrim i një tipi të dhënash thjesht në terma të çfarë veprimesh ofron dhe si sillen ato, pa përmendur si janë ndërtuar ato veprime. Është një kontratë. Thotë "mund t'i bësh këto gjëra, dhe ja çfarë premton secila", dhe hesht për të brendshmet.
Kontrata dhe implementimi
Ndihmon të mbash dy fjalë të ndara:
- Tipi abstrakt i të dhënave është kontrata: lista e veprimeve dhe rregullat që ndjekin. Për një numërues të thjeshtë, kontrata mund të jetë "nis nga zeroja,
rritshton një,vleraraporton totalin aktual". - Implementimi është kodi i vërtetë që e mban kontratën. Mund të kishte disa implementime të ndryshme të së njëjtës kontratë, secili me këmbimet e veta. Kodi që përdor vetëm veprimet e premtuara nuk e dallon dot cilin mori. Kodi që shkon përtej tyre, ose që i intereson sa zgjat një veprim, e dallon fare mirë.
Mendo një çelës drite. Kontrata është "shtyj lart për ndezje, shtyj poshtë për fikje". Nëse instalimi pas murit është i vjetër apo i ri, prej bakri apo diçka tjetër, nuk e ndryshon si e përdor çelësin. Çelësi është tipi abstrakt; instalimi është implementimi.
Pse e vlen ndarja
Të mbash kontratën ndaras nga implementimi të blen dy përparësi të vërteta.
Së pari, mund ta përdorësh një tip të dhënash duke mësuar vetëm kontratën e tij. S'të duhet të lexosh burimin e listës së Python-it për të ruajtur notat e tua në një. Veprimet e premtuara mjaftojnë.
Së dyti, kushdo që ndërton tipin mund ta ndryshojë implementimin lirisht, për sa kohë kontrata prapë qëndron. Nëse gjejnë një mënyrë më të shpejtë për të ruajtur të dhënat, kodi yt vazhdon të punojë pa u prekur, sepse u mbështet vetëm te premtimet, kurrë te mekanizmi. Kodi që mbështetet te kontrata mbijeton; kodi që fut duart te mekanizmi prishet në çastin që mekanizmi ndryshon.
Këshillë
Kur takon një strukturë të re të dhënash, mëso së pari kontratën e saj: çfarë mund të shtoj, çfarë mund të nxjerr, çfarë mund të pyes, dhe në çfarë radhe dalin gjërat mbrapsht? Zgjuarsia e brendshme mund të presë. Kontrata është ajo kundrejt së cilës vërtet programon.
Një shembull i punuar: një tabelë pikësh si kontratë
Le të themi se një lojë ka nevojë për një tabelë pikësh. Para se të shkruash një rresht kodi ruajtjeje, përshkruaj kontratën: çfarë duhet të bëjë një tabelë pikësh?
regjistro(ekipi): jep një pikë një ekipi.pikat(ekipi): raporton sa pikë ka një ekip.
Ky është i gjithë tipi abstrakt. Vetëm tani zgjedh një implementim, dhe një fjalor nga mësimi i mëparshëm përshtatet pastër:
def tabele_e_re():
return {}
def regjistro(tabela, ekipi):
tabela[ekipi] = tabela.get(ekipi, 0) + 1
def pikat(tabela, ekipi):
return tabela.get(ekipi, 0)
loja = tabele_e_re()
regjistro(loja, "kuq")
regjistro(loja, "kuq")
regjistro(loja, "blu")
print(pikat(loja, "kuq")) # 2
print(pikat(loja, "gjelber")) # 0
Pjesa tjetër e programit tënd thërret regjistro dhe pikat dhe s'e prek kurrë fjalorin drejtpërdrejt. Kjo është disiplina që të jep tipi abstrakt: nëse më vonë e ndërroje fjalorin me një ruajtje tjetër, secila prej atyre thirrjeve do të vazhdonte të punonte pa ndryshim, sepse u mbështetën vetëm te kontrata. Dy mësimet e ardhshme, për stack-et dhe radhët, janë dy kontrata të tjera pikërisht të këtij lloji.
Provoje tani
Mësimi përmendi një kontratë numëruesi: "nis nga zeroja, rrit shton një, vlera raporton totalin". Implementoje në stilin e tabelës së pikëve, duke e ruajtur numrin brenda një fjalori: numerues_i_ri() kthen {"numri": 0}, rrit(numeruesi) i shton një, dhe vlera(numeruesi) e kthen. Bëj një numërues, rrite tri herë, dhe shtyp vlerën. Pjesa tjetër e kodit s'e prek kurrë numrin drejtpërdrejt, vetëm kontratën.
Vëri të dyja njësitë në punë
Pohimi më sipër ia vlen të provohet e jo të besohet: se ndërrimi i ruajtjes poshtë do t'i linte të gjitha thirrjet duke punuar. Ja ndërrimi.
Praktikë e njësisë · 25 deri në 30 min
Ndërro zbatimin dhe shih kujt i mbijeton kodi
Ky mësim premton se nëse fjalori nën tabelën e rezultateve ndërrohej me diçka tjetër, çdo thirrje do të vazhdonte të punonte. Kjo ia vlen të provohet e jo të besohet. Puna jote rri në këtë shfletues: asgjë nuk ngarkohet, nuk vlerësohet dhe nuk ruhet.
Kontrata, pikërisht siç e thotë mësimi
record(board, team) -> give one point to a team points(board, team) -> report how many points a team has
Dy veprime. Kaq është i gjithë tipi abstrakt. Asgjë tjetër nuk premtohet.
1 · Parashiko
Një shok ekipi shkroi këto katër rreshta kundrejt tabelës. Sot ajo është ndërtuar mbi një fjalor. Për secilin rresht, thuaj nëse do ta bënte ende punën e vet po të ndryshonte zbatimi.
Pyet sa pikë ka e kuqja
print(points(game, "red"))
Listo çdo skuadër në tabelë
for team in game:
print(team)Numëro sa skuadra po luajnë
print(len(game))
Jepi një pikë të kaltrës
record(game, "blue")
Nëse ke ngecur, lexoje kontratën fjalë për fjalë
Kthehu te dy rreshtat e kontratës dhe lexoji sikur t'i kishte shkruar një jurist. Thonë se një skuadre mund t'i jepet një pikë, dhe se totali i një skuadre mund të raportohet. Kaq thonë.
Tani merr çdo rresht kodi dhe bëj një pyetje: a përdor ky vetëm ato dy veprime? Nëse po, është i sigurt. Nëse prek vetë tabelën, me një cikël, një gjatësi, një indeks apo një çelës, po shkon përtej kontratës brenda ruajtjes, dhe ruajtja është pjesa që lejohet të ndryshojë.
Ai test i vetëm i zgjidh të katër fragmentet pa ditur asgjë për listat apo fjalorët.
Nëse kjo iu duk e thjeshtë
Kur është heshtja projektim i duhur? Mësimi i dukshëm nga kjo praktikë është se kontratat duhet të premtojnë më shumë. Kjo është gjysmë e vërtetë dhe gjysma tjetër është kurth.
Çdo premtim që shton është një liri që ia heq atij që e zbaton. Premto se skuadrat kthehen sipas radhës kur shënuan, dhe ke ndaluar në heshtje çdo zbatim të ardhshëm që nuk e ruan radhën, përfshirë disa që do të ishin më të shpejtë. Premto një kërkim në kohë konstante dhe ke ndaluar versionin e thjeshtë me listë, që është krejt në rregull për tetë skuadra. Një kontratë që premton gjithçka mund të zbatohet vetëm në një mënyrë, dhe në atë pikë ka pushuar së qeni tip abstrakt fare.
Prandaj vetë set i Python-it nuk premton asnjë radhë, edhe pse çdo bashkësi e vërtetë ka njëfarë rregullimi të brendshëm. Refuzimi për ta premtuar e mban zbatimin të lirë, dhe të thotë ndershmërisht të mos varesh nga ajo që përndryshe mund ta vëresh.
Radha jote: merr klauzolën që sapo shkrove dhe argumento anën tjetër. Cilin zbatim e ndalon tani premtimi yt, dhe a ia vlen ai çmim për programin që ke vërtet?
Gjete diçka të paqartë, të vjetruar ose që mund të përmirësohet? Sugjero një përmirësim
Provo veten
- Me fjalët e tua, cili është ndryshimi mes një tipi abstrakt të të dhënave dhe implementimit të tij? Përdor idenë e çelësit të dritës ose një shembull tëndin.
- Pse mund autori i një tipi të dhënash ta ndryshojë si i ruan të dhënat pa i prishur programet që e përdorin, për sa kohë një gjë mbetet e njëjtë? Cila është ajo gjë?
- Në shembullin e tabelës së pikëve, pjesa tjetër e programit thërret vetëm
regjistrodhepikat. Pse ka rëndësi kjo nëse më vonë vendos t'i ruash pikët në një mënyrë krejt tjetër?
Nga vjen ky mësim
Ndërtuar mbi
- Data Structures and Algorithms
- Për të lexuar më tej: Brian Heinold, A Practical Introduction to Python Programming
Kurset e alphaPlan ndërtohen mbi programe të zhvilluara në klasë, e nuk shpiken për web-in. Kur një pohim mbështetet mbi një standard të jashtëm ose mbi një rast të raportuar, ai emërtohet më sipër që ta kontrollosh vetë e të mos na besosh në fjalë.
Ky kurs u zhvillua nga alphaPlan Center mbi bazën e programeve të realizuara në partneritet me rrjetin American Corners.
Gjete diçka të paqartë, të vjetruar ose që mund të përmirësohet? Sugjero një përmirësim