Path kanggo ngetik 4 yuta baris kode Python. Bagean 1

Dina iki kita nggawa menyang manungsa waΓ© bagean pisanan saka terjemahan materi babagan carane Dropbox ngurusi kontrol jinis kode Python.

Path kanggo ngetik 4 yuta baris kode Python. Bagean 1

Dropbox nyerat kathah ing Python. Iku basa sing digunakake banget, kanggo layanan back-end lan aplikasi klien desktop. Kita uga nggunakake Go, TypeScript lan Rust akeh, nanging Python minangka basa utama kita. Ngelingi skala kita, lan kita ngomong babagan mayuta-yuta baris kode Python, ternyata ngetik dinamis kode kasebut ora perlu rumit pemahaman lan wiwit mengaruhi produktivitas tenaga kerja. Kanggo ngurangi masalah iki, kita wis miwiti kanthi bertahap transisi kode kita kanggo mriksa jinis statis nggunakake mypy. Iki mbokmenawa sistem mriksa jinis mandiri sing paling populer kanggo Python. Mypy minangka proyek sumber terbuka, pangembang utama kerja ing Dropbox.

Dropbox minangka salah sawijining perusahaan pertama sing ngetrapake pamriksa jinis statis ing kode Python ing skala iki. Mypy digunakake ing ewonan proyek saiki. Alat iki kaping pirang-pirang, kaya sing dikandhakake, "dites ing perang." Kita wis adoh banget kanggo tekan ing ngendi kita saiki. Sadawane dalan, ana akeh usaha sing gagal lan eksperimen sing gagal. Kiriman iki nyakup riwayat mriksa jinis statis ing Python, wiwit wiwitane minangka bagean saka proyek risetku, nganti saiki, nalika mriksa jinis lan hinting jinis wis dadi umum kanggo pangembang sing ora kaetung sing nulis ing Python. Mekanisme iki saiki didhukung dening akeh alat kayata IDE lan penganalisa kode.

β†’ Wacanen bagean kapindho

Napa jinis mriksa perlu?

Yen sampeyan wis tau nggunakake mbosenke diketik Python, sampeyan bisa duwe sawetara kebingungan kanggo apa ana fuss kuwi sak statis typing lan mypy akhir-akhir iki. Utawa mungkin sampeyan seneng Python amarga ngetik dinamis, lan apa sing kedadeyan mung ngganggu sampeyan. Kunci kanggo nilai ngetik statis yaiku skala solusi: luwih gedhe proyek sampeyan, luwih akeh sampeyan condong menyang ngetik statis, lan pungkasane, sampeyan butuh banget.

Upaminipun proyek tartamtu wis tekan ukuran puluhan ewu baris, lan ternyata sawetara programer sing digunakake ing. Nggoleki proyek sing padha, adhedhasar pengalaman kita, kita bisa ujar manawa ngerti kode kasebut bakal dadi kunci supaya pangembang tetep produktif. Tanpa anotasi jinis, bisa dadi angel kanggo ngerteni, contone, argumen apa sing kudu diterusake menyang fungsi, utawa jinis fungsi sing bisa bali. Mangkene pitakonan umum sing asring angel dijawab tanpa nggunakake anotasi jinis:

  • Bisa bali fungsi iki None?
  • Apa sing kudu dadi argumentasi iki? items?
  • Apa jinis atribut id: int iku, str, utawa Mungkin sawetara jinis adat?
  • Apa argumen iki kudu dadi dhaptar? Apa bisa kanggo pass tuple menyang?

Yen sampeyan ndeleng cuplikan kode sing ditulis kanthi jinis ing ngisor iki lan nyoba mangsuli pitakon sing padha, ternyata iki minangka tugas sing paling gampang:

class Resource:
    id: bytes
    ...
    def read_metadata(self, 
                      items: Sequence[str]) -> Dict[str, MetadataItem]:
        ...

  • read_metadata ora bali None, wiwit jinis bali ora Optional[…].
  • Argumentasi items yaiku urutaning larik. Ora bisa diulang kanthi acak.
  • Atribut id yaiku senar bita.

Ing donya becik, siji bakal nyana kabeh subtleties kuwi bakal diterangake ing dokumentasi dibangun ing (docstring). Nanging pengalaman menehi akeh conto kasunyatan sing dokumentasi kuwi asring ora diamati ing kode karo kang sampeyan kudu bisa. Sanajan dokumentasi kasebut ana ing kode kasebut, siji ora bisa ngetung kanthi bener. Dokumentasi iki bisa dadi ora jelas, ora akurat, lan mbukak kanggo salah pangerten. Ing tim gedhe utawa proyek gedhe, masalah iki bisa dadi akut banget.

Nalika Python unggul ing tahap awal utawa pertengahan proyek, ing sawetara proyek sukses lan perusahaan sing nggunakake Python bisa ngadhepi pitakonan penting: "Apa kita kudu nulis ulang kabeh ing basa sing diketik kanthi statis?".

Sistem mriksa jinis kaya mypy ngrampungake masalah ing ndhuwur kanthi menehi pangembang basa resmi kanggo njlèntrèhaké jinis, lan mriksa manawa deklarasi jinis cocog karo implementasi program (lan, kanthi opsional, mriksa anané). Umumé, kita bisa ujar manawa sistem kasebut bisa digunakake kaya dokumentasi sing dicenthang kanthi teliti.

Panggunaan sistem kasebut nduweni kaluwihan liyane, lan wis ora pati penting:

  • Sistem mriksa jinis bisa ndeteksi sawetara kesalahan cilik (lan ora cilik). Conto khas yaiku nalika lali ngolah nilai None utawa kondisi khusus liyane.
  • Refactoring kode disederhanakake amarga sistem mriksa jinis asring akurat banget babagan kode sing kudu diganti. Ing wektu sing padha, kita ora perlu ngarep-arep 100% jangkoan kode kanthi tes, sing, ing kasus apa wae, biasane ora bisa ditindakake. Kita ora perlu kanggo delve menyang ambane saka tumpukan tilak kanggo mangerteni sabab saka masalah.
  • Malah ing proyek gedhe, mypy asring bisa nindakake mriksa jinis lengkap sajrone sekedhik. Lan eksekusi tes biasane njupuk puluhan detik utawa malah menit. Sistem mriksa jinis menehi umpan balik langsung marang programmer lan ngidini dheweke nindakake tugas kanthi luwih cepet. Dheweke ora perlu maneh nulis sing rapuh lan angel kanggo njaga tes unit sing ngganti entitas nyata kanthi moyoki lan tambalan mung kanggo entuk asil tes kode luwih cepet.

IDE lan editor kayata PyCharm utawa Visual Studio Code nggunakake kekuatan anotasi jinis kanggo nyedhiyakake pangembang kanthi ngrampungake kode, nyorot kesalahan, lan dhukungan kanggo konstruksi basa sing umum digunakake. Lan iki mung sawetara keuntungan saka ngetik. Kanggo sawetara programer, kabeh iki minangka argumen utama kanggo ngetik. Iki soko sing entuk manfaat langsung sawise implementasine. Kasus panggunaan kanggo jinis iki ora mbutuhake sistem pamriksa jinis sing kapisah kaya mypy, sanajan kudu dicathet yen mypy mbantu supaya anotasi jinis tetep konsisten karo kode.

Latar mburi mypy

Sejarah mypy diwiwiti ing Inggris, ing Cambridge, sawetara taun sadurunge aku gabung karo Dropbox. Aku wis melu, minangka bagΓ©an saka riset doktoral, ing manunggalaken basa statis diketik lan dinamis. Aku diilhami dening artikel babagan ngetik incremental dening Jeremy Siek lan Walid Taha, lan proyek Racket Typed. Aku nyoba golek cara kanggo nggunakake basa pamrograman sing padha kanggo macem-macem proyek - saka skrip cilik nganti basis kode sing dumadi saka pirang-pirang yuta garis. Ing wektu sing padha, aku pengin mesthekake yen ing proyek apa wae, ora kudu nggawe kompromi sing gedhe banget. Bagean penting saka kabeh iki yaiku ide kanggo mindhah alon-alon saka prototipe prototipe sing ora diketik menyang produk rampung sing diketik kanthi statis. Dina iki, gagasan-gagasan kasebut umume dianggep ora dikarepake, nanging ing taun 2010 iki minangka masalah sing isih aktif ditliti.

Karya asliku ing jinis mriksa ora ngarahake Python. Nanging, aku nggunakake basa "krasan" cilik Alore. Iki minangka conto sing bakal ngidini sampeyan ngerti apa sing kita gunakake (jenis anotasi opsional ing kene):

def Fib(n as Int) as Int
  if n <= 1
    return n
  else
    return Fib(n - 1) + Fib(n - 2)
  end
end

Nggunakake basa asli sing disederhanakake minangka pendekatan sing umum digunakake ing riset ilmiah. Iki pancene, paling ora amarga ngidini sampeyan nindakake eksperimen kanthi cepet, lan uga amarga kasunyatan manawa apa sing ora ana hubungane karo sinau bisa gampang diabaikan. Basa pemrograman ing donya nyata cenderung dadi fenomena skala gedhe kanthi implementasine rumit, lan iki nyuda eksperimen. Nanging, asil apa wae adhedhasar basa sing disederhanakake katon rada curiga, amarga nalika entuk asil kasebut, panaliti bisa ngorbanake pertimbangan sing penting kanggo panggunaan praktis basa.

Pendhaftaran jinis checker kanggo Alore katon banget janjeni, nanging aku wanted kanggo nyoba metu dening èkspèrimèn saka kode nyata, kang, sampeyan bisa ngomong, iki ora ditulis ing Alore. Untunge kanggo aku, basa Alore umume adhedhasar ide sing padha karo Python. Cukup gampang kanggo nggawe maneh typechecker supaya bisa digunakake karo sintaks lan semantik Python. Iki ngidini kita nyoba mriksa jinis kode Python open source. Kajaba iku, aku nulis transpiler kanggo ngowahi kode sing ditulis ing Alore menyang kode Python lan digunakake kanggo nerjemahake kode typechecker. Saiki aku duwe sistem mriksa jinis sing ditulis ing Python sing ndhukung subset saka Python, sawetara jinis basa kasebut! (Keputusan arsitektur tartamtu sing cocog karo Alore ora cocog karo Python, lan iki isih katon ing bagean saka basis kode mypy.)

Nyatane, basa sing didhukung dening sistem jinisku ora bisa diarani Python ing wektu iki: iki minangka varian saka Python amarga sawetara watesan sintaks anotasi jinis Python 3.

Iku katon kaya campuran Jawa lan Python:

int fib(int n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Salah sawijining gagasanku ing wektu iku yaiku nggunakake anotasi jinis kanggo nambah kinerja kanthi nggabungake Python iki menyang C, utawa bisa uga JVM bytecode. Aku entuk tahap nulis prototipe compiler, nanging aku nolak ide iki, amarga mriksa jinis dhewe katon migunani.

Aku pungkasane nampilake proyekku ing PyCon 2013 ing Santa Clara. Aku uga ngedika bab iki karo Guido van Rossum, diktator Python benevolent kanggo urip. Dheweke nggawe percoyo aku kanggo nyelehake sintaks dhewe lan tetep nganggo sintaks Python standar 3. Python 3 ndhukung anotasi fungsi, supaya contoku bisa ditulis maneh kaya sing kapacak ing ngisor iki, ngasilake program Python normal:

def fib(n: int) -> int:
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Aku kudu nggawe sawetara kompromi (pisanan, aku pengin Wigati sing aku nemokke sintaks dhewe kanggo alesan iki). Utamane, Python 3.3, versi basa paling anyar ing wektu kasebut, ora ndhukung anotasi variabel. Aku rembugan karo Guido dening e-mail macem-macem kemungkinan kanggo desain sintaksis anotasi kuwi. Kita mutusake nggunakake komentar jinis kanggo variabel. Iki dadi tujuan sing dituju, nanging rada rumit (Python 3.6 menehi sintaks sing luwih apik):

products = []  # type: List[str]  # Eww

Komentar jinis uga migunani kanggo ndhukung Python 2, sing ora duwe dhukungan kanggo anotasi jinis:

f fib(n):
    # type: (int) -> int
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Pranyata yen iki (lan liyane) trade-off ora pati penting - keuntungan saka ngetik statis tegese pangguna enggal lali babagan sintaks sing kurang sampurna. Amarga ora ana konstruksi sintaksis khusus sing digunakake ing kode Python sing wis dicenthang, alat Python lan pangolahan pangolahan kode sing ana terus bisa digunakake kanthi normal, dadi luwih gampang kanggo pangembang sinau alat anyar kasebut.

Guido uga ngyakinake aku supaya melu Dropbox sawise ngrampungake skripsi. Iki ngendi bagean paling menarik saka crita mypy diwiwiti.

Terus ...

Para pamaca ingkang kinurmatan! Yen sampeyan nggunakake Python, matur marang kita babagan ukuran proyek sing dikembangake ing basa iki.

Path kanggo ngetik 4 yuta baris kode Python. Bagean 1
Path kanggo ngetik 4 yuta baris kode Python. Bagean 1

Source: www.habr.com

Add a comment