Hacker News

Python төрлийн шалгагч харьцуулалт: хоосон савны дүгнэлт

Сэтгэгдэл

1 min read Via pyrefly.org

Mewayz Team

Editorial Team

Hacker News

Яагаад хоосон савнууд Python төрлийн шалгагчийг эвддэг вэ? Та энэ талаар юу хийж чадах вэ?

2015 онд PEP 484 төрлийн зааварчилгааг нэвтрүүлснээс хойш Python-ын аажмаар бичих систем нэлээд боловсорч гүйцсэн. Өнөөдөр сая сая хөгжүүлэгчид үйлдвэрлэлд гарахаасаа өмнө алдааг илрүүлэхийн тулд статик төрлийн шалгагч ашигладаг. Гэсэн хэдий ч туршлагатай инженерүүдийг хүртэл урам хугарахуйц системийн нарийн төвөгтэй булан бий: хоосон сав ямар төрөлтэй вэ? Та x = []-г тайлбаргүйгээр бичих үед төрөл шалгагч таах ёстой бөгөөд өөр шалгагч өөр өөрөөр тааварлана. Энэ зөрүү нь том кодын баазыг ажиллуулж буй багуудад бодит асуудал үүсгэдэг бөгөөд төрөл шалгагчийг сэлгэх эсвэл нэгтгэх нь нэг шөнийн дотор олон зуун гэнэтийн алдаа гаргахад хүргэдэг.

Энэ нийтлэлд mypy, pyright, pytype, pyre гэсэн дөрвөн үндсэн Python төрлийн шалгагч хоосон савны дүгнэлтийг хэрхэн зохицуулдаг, тэдгээр нь яагаад санал нийлэхгүй байгаа, мөн та ямар хэрэглүүрийн сонголтоос үл хамааран төрөлд аюулгүй Python бичихийн тулд ямар практик стратеги хэрэглэж болохыг задалсан болно.

Гол асуудал: Хоосон савнууд нь угаасаа хоёрдмол утгатай

Python-ийн энэ хор хөнөөлгүй мөрийг авч үзье: үр дүн = []. үр дүн нь жагсаалт[int] мөн үү? жагсаалт[str] уу? жагсаалт[dict[str, Any]] уу? Нэмэлт контекст байхгүй бол үнэхээр мэдэх арга байхгүй. Python-ийн ажиллах цаг нь хамаагүй - жагсаалтууд нь угаасаа нэг төрлийн бус байдаг - гэхдээ статик төрлийн шалгагчид өөрсдийн ажлыг хийхийн тулд хувьсагч бүрт тодорхой төрлийг оноох шаардлагатай. Энэ нь Python-ийн динамик уян хатан байдал болон статик шинжилгээгээр хангах баталгааны хооронд үндсэн хурцадмал байдлыг үүсгэдэг.

Асуудал нь толь бичиг, багцуудтай нийлдэг. Хоосон {} нь үнэндээ dict болохоос багц биш бөгөөд энэ нь төрлийн түвшний хоёрдмол утга дээр үг хэллэгийн хоёрдмол утга нэмдэг. Мөн үүрлэсэн контейнерууд — defaultdict(list) эсвэл results = {k: [] for k in keys} гэж бодоорой — дүгнэлтийн хөдөлгүүрийг хязгаарт нь хүргэнэ. Төрөл шалгагч бүр өөрийн эвристикийг боловсруулсан бөгөөд ялгаа нь ихэнх хөгжүүлэгчдийн ойлгосноос илүү чухал юм.

Бодит ажлын ачааллыг боловсруулдаг үйлдвэрлэлийн системд - энэ нь хэрэглэгчийн бүртгэлийг зохицуулдаг CRM, мөрийн зүйл үүсгэдэг нэхэмжлэхийн модуль эсвэл хэмжигдэхүүнүүдийг нэгтгэдэг аналитик дамжуулах хоолойн аль нь ч бай - хоосон савнууд эхлүүлэх загвар хэлбэрээр байнга гарч ирдэг. Тэдний төрлийг буруу авах нь зөвхөн линтерийн анхааруулгыг үүсгэдэггүй; Энэ нь ажиллах цаг руу шилждэг жинхэнэ алдааг нууж чадна.

Mypy: Ямар ч далдтай хойшлогдсон дүгнэлт

Хамгийн эртний бөгөөд хамгийн өргөн хэрэглэгддэг Python төрлийн шалгагч Mypy нь хоосон саванд харьцангуй зөөлөн ханддаг. Функцийн хүрээнд x = []-тэй тулгарах үед энэ нь төрлийн шийдвэрийг хойшлуулахыг оролдох ба дараагийн ашиглалтаас элементийн төрлийг гаргах. Хэрэв та x = [] дараа нь x.append(42) гэж бичвэл mypy list[int] гэсэн дүгнэлт гаргах болно. Энэхүү "нэгдэх" стратеги нь контейнер нь ижил хүрээнд байрладаг энгийн тохиолдлуудад гайхалтай сайн ажилладаг.

Гэсэн хэдий ч, mypy-ийн зан байдал контекст болон хатуу байдлын тохиргооноос хамааран эрс өөрчлөгддөг. Модулийн хамрах хүрээ (дээд түвшний код) эсвэл савыг дүүргэхээс өмнө өөр функц руу шилжүүлэх үед mypy ихэвчлэн жагсаалт[Аливаа] руу буцдаг. --strict тугийн дор энэ нь алдааг өдөөх боловч анхдагч горимд чимээгүйхэн дамждаг. Энэ нь mypy-г хатуу горимгүйгээр ажиллуулж байгаа багууд нь төрлийн системээс зугтах нүхний үүрэг гүйцэтгэдэг олон арван далд хэлбэрээр бичигдсэн контейнеруудыг хуримтлуулж, зорилгоо биелүүлж чадна гэсэн үг юм.

Нэг нарийн үйлдэл: 0.990-ээс өмнөх mypy хувилбарууд заримдаа жагсаалт[Үл мэдэгдэх]-ийг дотооддоо гаргадаг бөгөөд дараа нь даалгавар дээр жагсаалт[Ямар нэгэн] болж өргөждөг. 0.990-ээс хойш дүгнэлт нь чангарсан боловч өөрчлөлт нь өөрийн мэдэлгүй зөвшөөрөгдсөн зан төлөвт найдаж байсан гайхалтай олон тооны бодит кодын суурийг эвдсэн. Энэ бол байнга давтагддаг сэдэв юм — хоосон савны дүгнэлтэнд хийсэн өөрчлөлтүүд нь хэв маяг нь хаа сайгүй байдаг тул хамгийн их саад учруулж буй төрлийн шалгагч шинэчлэлтүүдийн нэг юм.

Зохиогчийн эрх: Хатуу дүгнэлт ба "Үл мэдэгдэх" төрөл

Microsoft-ын хөгжүүлж, Pylance-г VS Code-д ашигладаг Pyright нь огт өөр философийн байр суурийг баримталдаг. Аливаа руу чимээгүйхэн буцахын оронд pyright нь Үл мэдэгдэх (одоохондоо тодорхойлогдоогүй төрөл) болон Аль ч (төрлийн шалгалтаас илт татгалзах)-ыг ялгадаг. Таныг зохиогчийн эрхийн хатуу горимд x = [] гэж бичихэд энэ нь жагсаалт[Үл мэдэгдэх]-ийг гаргаж, оношийг мэдээлснээр таныг тайлбар өгөхийг албаддаг.

Pyright мөн хүрээг багасгах талаар илүү түрэмгий ханддаг. Хэрэв та бичвэл:

  • x = [], дараа нь x.append("hello") - зохиогчийн эрх жагсаалт[str]
  • -ыг гаргадаг.
  • x = [] дараа нь x.append(1) дараа нь x.append("сайн уу") - зохиогчийн эрх жагсаалт[int | str]
  • x = [] нь list[int] хүлээгдэж буй функц руу шууд шилжсэн — pyright нь дуудлагын сайтын контекстээс list[int] гэсэн дүгнэлт гаргадаг
  • x = [] буцах төрлийн тайлбаргүй функцээс буцсан — pyright нь таамаглахын оронд алдааг мэдээлдэг

Энэ хоёр чиглэлтэй дүгнэлт нь (дараагийн хэрэглээ болон дуудлагын сайтуудын хүлээгдэж буй төрлүүдийг хоёуланг нь ашиглан) хоосон савны mypy-ээс илүү нарийвчлалтай болгодог. Хэд хэдэн нээлттэй эх сурвалжийн шилжилтийн тайланд хийсэн дүн шинжилгээнээс үзэхэд pyright-ийн хатуу горим нь mypy-ийн хатуу горимтой харьцуулахад ердийн тэмдэглэгээгүй кодын бааз дээр ойролцоогоор 30-40%-иар илүү асуудал үүсгэдэг. CRM, цалингийн бүртгэл, аналитикийг хамарсан харилцан уялдаатай 207 модулийг удирддаг платформ гэх мэт нарийн төвөгтэй backend системийг бий болгож буй багуудын хувьд pyright-ийн хатуу байдал нь энгийн дүгнэлт гаргахад үл тоомсорлож болох нарийн интерфэйсийн тохиромжгүй байдлыг илрүүлдэг.

Pytype болон Pyre: Бага аялсан замууд

Google-н pytype нь магадгүй хамгийн прагматик хандлагыг ашигладаг. Тэмдэглэгээ шаардах эсвэл Аль ч руу буцахын оронд pytype нь функцын хил хязгаарыг дамнан контейнер хэрхэн ашиглагдаж байгааг хянахын тулд бүтэн програмын шинжилгээ-г ашигладаг. Хэрэв та нэг функцэд хоосон жагсаалт үүсгээд бүхэл тоо нэмдэг нөгөө рүү шилжүүлбэл pytype нь ихэвчлэн ямар ч тайлбаргүйгээр list[int] гэсэн дүгнэлт гаргадаг. Энэхүү хөндлөн функцын дүгнэлт нь тооцооллын хувьд үнэтэй байдаг — pytype нь том кодын суурь дээрх mypy эсвэл pyright-аас хамаагүй удаан байдаг боловч энэ нь тэмдэглэгээгүй код дээр цөөн худал эерэг үр дүн гаргадаг.

Pytype нь хоосон савны "хэсэгчилсэн төрөл" гэсэн ойлголтыг мөн танилцуулдаг. Шинээр үүсгэгдсэн [] нь шалгагч илүү их хэрэглээтэй тулгарснаар аажмаар сайжруулсан хэсэгчилсэн төрлийг авдаг. Энэ нь үзэл баримтлалын хувьд дэгжин боловч хэсэгчилсэн төрлийг бүрэн шийдвэрлэх боломжгүй үед, тухайлбал, хоосон савыг дүүргэхгүйгээр хэд хэдэн функцээр дамжих зэрэг төөрөгдүүлсэн алдааны мессежийг үүсгэж болно.

💡 DID YOU KNOW?

Mewayz replaces 8+ business tools in one platform

CRM · Invoicing · HR · Projects · Booking · eCommerce · POS · Analytics. Free forever plan available.

Start Free →

Энэ хооронд Мета-н pyre нь mypy-ийн зан төлөвт ойртсон ч илүү хатуу өгөгдмөлтэй байдаг. Pyre нь x = []жагсаалт[үл мэдэгдэх] гэж үздэг бөгөөд ихэнх контекстэд тайлбар хийх шаардлагатай. Пир өөр өөр байдаг нь вэб фреймворкийн нийтлэг хэв маяг болох хоосон толь бичгийг kwargs болгон ашиглах явдал юм. Pyre нь түлхүүр үгийн аргументын контекстээс толь бичгийн төрлийг гаргах тусгай тохиолдлын логиктой бөгөөд энэ нь хүрээ-хүнд кодын сан дахь тэмдэглэгээний ачааллыг бууруулдаг. Ихэнх орчин үеийн вэб програмууд нь тохиргоо болон хүсэлтийг боловсруулахдаа толь бичгийг задлах аргыг ихээр ашигладаг тул энэхүү прагматизм нь үр өгөөжөө өгдөг.

Бодит ертөнцийн нөлөө: Дүгнэлтийн зөрүү хазах үед

Үйлдвэрлэлийн кодын бааз дээр туршиж үзэх хүртэл төрлийн шалгагч хоорондын ялгаа нь академик мэт санагдаж магадгүй. Бизнесийн хэрэглээний программуудын нийтлэг хэв маягийг авч үзье: нөхцөлт байдлаар бөглөх өгөгдлийн бүтцийг эхлүүлэх.

Хамгийн аюултай хоосон савнууд нь даамны төрлийн далбаа биш бөгөөд тэдгээр нь таамагласан ямар ч төрлөөр чимээгүйхэн дамждаг ба энэ нь үндсэн чиг хандлагыг арилгах бараг боломжгүй TypeError-тай ажиллах үед доод урсгалын функц гацах хүртэл үл нийцэх өгөгдлийг сануулгагүйгээр хуримтлуулах боломжийг олгодог.

Тодорхой жишээ: Финтекийн гарааны баг үйлдвэрлэлийн асуудлыг дибаглахад гурван өдөр зарцуулсан гэж мэдээлсэн бөгөөд төлбөр боловсруулах функцээр эхлүүлсэн хоосон жагсаалтыг mypy-ээр жагсаалт[Аливаа] гэж дүгнэсэн байна. Жагсаалт нь валютын дүнгийн Аравтын объектуудыг агуулсан байх ёстой байсан ч кодын замд оронд нь float утгыг нэмж оруулсан байна. Mypy-ийн зөөлөн дүгнэлт үүнийг чимээгүйхэн зөвшөөрөв. Хөвөгч арифметикийн бөөрөнхийллийн алдаа нь 12,000 нэхэмжлэхийн багцад 0.01 долларын зөрүүтэй болоход л алдаа гарсан. Хэрэв тэд хатуу горимд pyright ашигласан эсвэл хоосон жагсаалтыг жагсаалт[Аравтын] гэж тэмдэглэсэн бол алдааг боловсруулах үед баригдах байсан.

Платтформ нь 138,000 гаруй хэрэглэгчийн дансанд нэхэмжлэх, цалингийн тооцоо, санхүүгийн аналитик боловсруулдаг Mewayz-д энэ төрлийн аюулгүй байдлын зөрүү нь онолын хувьд биш бөгөөд энэ нь цалингийн зөв гүйлгээ болон өндөр өртөгтэй дахин тооцооллын хоорондох ялгаа юм. Контейнерыг эхлүүлэхийн тулд хатуу бичих сахилга бат нь үйлдвэрлэлийн сэтгэл хөдөлгөм ослоос сэргийлдэг "уйтгартай" инженерийн практикуудын нэг юм.

Хамгаалах чингэлэгийг эхлүүлэх шилдэг туршлагууд

Танай баг ямар төрлийн шалгагч ашиглаж байгаагаас үл хамааран хоосон савны тодорхой бус байдлыг бүрэн арилгах тодорхой стратеги байдаг. Зорилго нь хоосон савны дүгнэлтэд хэзээ ч найдахгүй — төрлийг тодорхой болго, ингэснээр таны код бүх шалгагчийг ашиглах боломжтой бөгөөд хувилбаруудын хооронд дүгнэлт хийх өөрчлөлтөөс хамгаална.

  1. Үргэлж хоосон савны хувьсагчдыг тэмдэглэ. үр дүн = []-ийн оронд үр дүн: list[int] = [] гэж бичнэ. Хадгалсан дибаг хийх хугацаатай харьцуулахад бага зэргийн дэлгэрэнгүй мэдээлэл өгөх зардал бага байна. Энэ ганц дадлага нь хоосон савны дүгнэлтийн асуудлын 80 орчим хувийг арилгадаг.
  2. Нэгдмэл контейнерт үйлдвэрийн функцуудыг ашиглана уу. cache = {}-ийн оронд def make_cache() -> dict[str, list[UserRecord]]: буцах {} гэх мэт функц бичнэ үү. Буцаах төрлийн тэмдэглэгээ нь төлөвлөсөн төрлийг хоёрдмол утгагүй, өөрөө баримтжуулах боломжтой болгодог.
  3. Хичээлгүй төрлүүдэд бичигдсэн бүтээгчийг илүүд үзнэ үү. Олонлогийн ойлголтын дүгнэлтэнд найдахын оронд зүйл: set[int] = set() гэж бичнэ үү. defaultdict болон Counter-ийн хувьд үргэлж төрлийн параметрийг оруулна уу: тооцоог: Counter[str] = Counter().
  4. Шинэ кодын төрөл шалгагчийн хатуу горимыг тохируулна уу. Mypy болон pyright хоёулаа нэг файл эсвэл лавлах тохиргоог дэмждэг. Хуучин кодыг аажмаар шилжүүлэхийн зэрэгцээ шинэ модулиудыг хатуу шалгахыг идэвхжүүлнэ үү. Энэ нь далд хэлбэрээр бичигдсэн шинэ сав хуримтлагдахаас сэргийлнэ.
  5. Өөрийн CI дамжуулах хоолойд төрөл шалгагчийн харьцуулалтыг нэмнэ үү. Таны кодын сан дээр mypy болон pyright хоёрыг ажиллуулснаар дүгнэлтийн зөрүүг эрт илрүүлдэг. Хэрэв загвар нэг шалгагчийг давсан ч нөгөө шалгагчийг давсан бол энэ нь тухайн төрөл хангалттай тодорхой бус байгаагийн дохио юм.

Том зураг: Төрөл шалгах нь багийн дадлага

Хоосон савны дүгнэлт нь эцсийн дүндээ Python төрлийн систем дэх илүү том сорилтуудын бичил ертөнц юм: тав тухтай байдал, аюулгүй байдлын хоорондох хурцадмал байдал. Python-ийн "Бид бүгд зөвшөөрч буй насанд хүрэгчид" гэсэн философи нь прототип болон скрипт хийхэд маш сайн ажилладаг боловч олон мянган хэрэглэгчдэд үйлчилдэг үйлдвэрлэлийн системд илүү хүчтэй баталгаа хэрэгтэй. Дөрвөн үндсэн төрлийн шалгагч []-ийн төрөл шиг энгийн зүйл дээр санал нийлэхгүй байгаа нь Python шивэх экосистем төлөвшсөн хэвээр байгааг харуулж байна.

Цөөн хэдэн бичил үйлчилгээ эсвэл Mewayz-ийн бизнесийн үйлдлийн систем зэрэг хоорондоо уялдаатай олон зуун модулиудтай нэгдсэн системийг удирдаж байгаа эсэхээс үл хамааран нарийн төвөгтэй платформуудыг барьж буй инженерийн багуудад өгөх практик зөвлөгөө нь маш энгийн: хоосон савны дүгнэлтэнд найдах хэрэггүй, төрөл шалгагч сонгож, үүнийг хатуу тохируулаарай, мөн ийм төрлийн баримт бичгийг машинд тохиолдох боломжгүй гэж үзэж болно. []-ийн оронд жагсаалт[Нэхэмжлэх] бичихэд зарцуулсан таван минут нь таны кодын бааз томрох үед дибаг хийх цагийг хэмнэх болно.

PEP 696 (өгөгдмөл төрлийн параметрүүд) болон PEP 695 (төрлийн параметрийн синтакс) нь Python-ын шинэ хувилбарууд дээр буусаар байх тусам тодорхой бичих эргономик сайжирсаар байх болно. "Тэмдэглэгээтэй" болон "тэмдэглэгдээгүй" Python-ийн хоорондох ялгаа багасна. Гэвч тэр өдрийг хүртэл тодорхой контейнерийн төрлүүд нь Python хөгжүүлэгчийн хэрэгслийн хамгийн өндөр ROI-ийн нэг хэвээр байгаа бөгөөд энэ нь модуль бүр, спринт бүр болон үйлдвэрлэлийн байршил бүрт нийлмэл хүү төлдөг жижиг сахилга бат юм.

Өнөөдөр бизнесийн үйлдлийн системээ байгуулаарай

Чөлөөт ажилчдаас эхлээд агентлаг хүртэл Mewayz нь 207 нэгдсэн модулиудаар 138,000+ бизнесийг эрхэлдэг. Үнэгүй эхлүүлээрэй, өсч томрох үедээ сайжруулаарай.

Үнэгүй бүртгэл үүсгэх→

Байнга асуудаг асуултууд

Яагаад шивэгчид хоосон жагсаалтын төрлийг хүлээн зөвшөөрч чадахгүй байна вэ?

Таныг `x = []` гэж бичих үед төрөл шалгагч тодорхой зөвлөмжгүй төрлийг гаргах ёстой. Янз бүрийн шалгагчид өөр өөр стратеги ашигладаг: зарим нь `жагсаалт[Аливаа]` (ямар нэгэн зүйлийн жагсаалт) гэж дүгнэдэг бол зарим нь `жагсаалт[Үгүй]` гэх мэт илүү тодорхой боловч буруу төрлийг гаргаж болно. Энэ нь бүх нийтийн стандарт дутагдалтай байгаа нь тэд санал нийлэхгүй байгаагийн шалтгаан юм. Олон тооны шалгагч ашигладаг төслүүдийн хувьд энэ зөрчил нь нэг хэрэглүүрт дүн шинжилгээ хийх, нөгөөд дамжих гол толгойн өвчин байж болно.

Хоосон савны алдааг засах хамгийн энгийн арга юу вэ?

Хамгийн хялбар шийдэл бол тодорхой төрлийн тайлбар өгөх явдал юм. `my_list = []`-ын оронд `my_list: list[str] = []` гэж бичнэ үү. Энэ нь төрөл шалгагчийн бүх ойлгомжгүй байдлыг арилгаж, mypy, Pyright, Pyre зэрэг янз бүрийн хэрэгслүүдийн тогтвортой байдлыг хангана. Дүгнэлтийн алдаанаас урьдчилан сэргийлэхийн тулд бүх хоосон савыг эхлүүлэхэд энэ дасгалыг хийхийг зөвлөж байна.

Ангийн тодорхойлолт доторх хоосон савнуудыг би хэрхэн зохицуулах вэ?

Ангиудын доторх тэмдэглэгээ нь тусгай зохицуулалт шаарддаг тул энэ нь нийтлэг асуудал юм. Жагсаалт нь ангийн атрибут байхаар төлөвлөж байгаа бол та `from __future__ import annotations` импорт эсвэл `ClassVar` тэмдэглэгээг ашиглах ёстой. Жишээ нь, ` анги MyClass: my_list: ClassVar[жагсаалт[str]] = []`. Үүнгүйгээр төрөл шалгагч нь төрлийг зөв дүгнэж чадахгүй тул алдаа гаргахад хүргэж болзошгүй.

Томоохон төслүүдэд бичих эдгээр асуудлыг шийдвэрлэхэд туслах хэрэгслүүд байдаг уу?

Тийм ээ, Pyright (VS Code дахь Pylance-г идэвхжүүлдэг) зэрэг дэвшилтэт төрлийн шалгагч нь нарийн төвөгтэй дүгнэлтийг боловсруулахдаа маш сайн байдаг. Томоохон кодын баазуудын хувьд Mewayz (сард $19 үнээр 207 шинжилгээний модуль санал болгодог) зэрэг платформууд нь илүү гүнзгий, илүү тууштай төрлийн шалгалт өгч, нийтлэлд авч үзсэн зөрчилдөөнийг багасгаж, тэмдэглэгээний практикийг танай багийн хэмжээнд хэрэгжүүлэхэд тусалдаг.

Try Mewayz Free

All-in-one platform for CRM, invoicing, projects, HR & more. No credit card required.

Start managing your business smarter today

Join 30,000+ businesses. Free forever plan · No credit card required.

Ready to put this into practice?

Join 30,000+ businesses using Mewayz. Free forever plan — no credit card required.

Start Free Trial →

Ready to take action?

Start your free Mewayz trial today

All-in-one business platform. No credit card required.

Start Free →

14-day free trial · No credit card · Cancel anytime