Hari ini kami menerbitkan bagian kedua dari terjemahan materi, yang dikhususkan untuk mengetik anotasi dengan Python.

→
Bagian pertamaBagaimana Python mendukung tipe data?
Python adalah bahasa yang diketik secara dinamis. Ini berarti bahwa jenis variabel yang digunakan diperiksa hanya selama eksekusi program. Dalam contoh yang diberikan di bagian sebelumnya artikel, orang dapat melihat bahwa seorang programmer yang menulis dengan Python tidak perlu merencanakan jenis variabel dan berpikir tentang berapa banyak memori yang akan diperlukan untuk menyimpan datanya.
Inilah yang terjadi ketika Anda menyiapkan kode Python Anda untuk dieksekusi: “Dalam Python, kode sumber dikonversi menggunakan CPython menjadi bentuk yang jauh lebih sederhana yang disebut bytecode. Bytecode terdiri dari instruksi yang, pada dasarnya, mirip dengan instruksi prosesor. Tetapi mereka tidak dieksekusi oleh prosesor, tetapi oleh sistem perangkat lunak yang disebut mesin virtual. (Ini bukan tentang mesin virtual yang kemampuannya memungkinkan Anda untuk menjalankan seluruh sistem operasi pada mereka. Dalam kasus kami, ini adalah lingkungan yang merupakan versi sederhana dari lingkungan yang tersedia untuk program yang berjalan pada prosesor). "
Bagaimana CPython mengetahui tipe variabel apa yang seharusnya ketika menyiapkan program untuk dieksekusi? Bagaimanapun, kami tidak menunjukkan tipe ini. CPython tidak tahu tentang ini. Dia hanya tahu bahwa variabel adalah objek. Segala sesuatu di Python adalah
objek , setidaknya sampai ternyata sesuatu memiliki tipe yang lebih spesifik.
Sebagai contoh, Python menganggap sebagai string segala sesuatu yang tertutup dalam tanda kutip tunggal atau ganda. Jika Python menemukan angka, itu menganggap bahwa nilai yang sesuai adalah tipe numerik. Jika kami mencoba melakukan sesuatu dengan entitas yang tidak dapat dilakukan dengan entitas jenisnya, Python akan memberi tahu kami nanti.
Pertimbangkan pesan kesalahan berikut yang muncul ketika Anda mencoba menambahkan string dan nomor:
name = 'Vicki' seconds = 4.71; --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-9-71805d305c0b> in <module> 3 4 ----> 5 name + seconds TypeError: must be str, not float
Sistem memberitahu kita bahwa itu tidak dapat menambahkan string dan angka floating-point. Selain itu, fakta bahwa
name
adalah string, dan
seconds
adalah angka, tidak menarik sistem sampai upaya dilakukan untuk menambahkan
name
dan
seconds
.
Dengan kata lain, dapat digambarkan
sebagai berikut : “Mengetik bebek digunakan saat melakukan penambahan. Python tidak tertarik pada tipe yang dimiliki objek tertentu. Yang membuat sistem tertarik adalah apakah ia mengembalikan panggilan bermakna ke metode penambahan. Jika tidak demikian, kesalahan dikeluarkan. "
Apa artinya itu? Ini berarti bahwa jika kita menulis program dengan Python, kita tidak akan menerima pesan kesalahan sampai juru bahasa CPython terlibat dalam pelaksanaan baris yang sama di mana ada kesalahan.
Pendekatan ini tidak nyaman ketika diterapkan dalam tim yang bekerja pada proyek besar. Faktanya adalah bahwa dalam proyek-proyek tersebut mereka bekerja tidak dengan variabel yang terpisah, tetapi dengan struktur data yang kompleks. Dalam proyek semacam itu, beberapa fungsi dipanggil oleh yang lain, dan pada gilirannya, fungsi itu dipanggil oleh beberapa fungsi lainnya. Anggota tim harus dapat dengan cepat memeriksa kode untuk proyek mereka. Jika mereka tidak dapat menulis tes yang baik yang mendeteksi kesalahan dalam proyek sebelum mereka dimasukkan ke dalam produksi, ini berarti bahwa proyek tersebut dapat mengharapkan masalah besar.
Sebenarnya, di sini kita sampai pada percakapan tentang ketik anotasi dengan Python.
Kita dapat mengatakan bahwa, secara umum, penggunaan anotasi jenis memiliki banyak
kekuatan . Jika Anda bekerja dengan struktur data yang kompleks atau fungsi yang mengambil banyak nilai input, menggunakan anotasi sangat menyederhanakan bekerja dengan struktur dan fungsi yang sama. Terutama - beberapa saat setelah penciptaan mereka. Jika Anda hanya memiliki satu fungsi dengan satu parameter, seperti dalam contoh yang diberikan di sini, maka bekerja dengan fungsi seperti itu, dalam hal apa pun, sangat sederhana.
Bagaimana jika kita perlu bekerja dengan fungsi kompleks yang mengambil banyak nilai input yang mirip dengan ini dari dokumentasi
PyTorch :
def train(args, model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() if batch_idx % args.log_interval == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))
Apa itu
model
? Tentu saja, kita dapat menggali basis kode dan mencari tahu:
model = Net().to(device)
Tapi alangkah baiknya jika Anda bisa menentukan jenis
model
dalam tanda tangan fungsi dan menyelamatkan diri dari analisis kode yang tidak perlu. Mungkin akan terlihat seperti ini:
def train(args, model (type Net), device, train_loader, optimizer, epoch):
Bagaimana dengan
device
? Jika Anda mencari-cari kode, Anda dapat menemukan yang berikut:
device = torch.device("cuda" if use_cuda else "cpu")
Sekarang kita dihadapkan dengan pertanyaan tentang apa itu alat
torch.device
. Ini adalah tipe khusus PyTorch. Uraiannya dapat ditemukan di bagian yang
sesuai dari dokumentasi PyTorch.
Alangkah baiknya jika kita bisa menentukan tipe
device
dalam daftar argumen fungsi. Dengan demikian, kami akan menghemat banyak waktu bagi mereka yang harus menganalisis kode ini.
def train(args, model (type Net), device (type torch.Device), train_loader, optimizer, epoch):
Pertimbangan ini dapat berlanjut untuk waktu yang sangat lama.
Hasilnya, ternyata anotasi jenis sangat berguna bagi seseorang yang menulis kode. Tetapi mereka juga bermanfaat bagi mereka yang membaca kode orang lain. Jauh lebih mudah untuk membaca kode yang diketik daripada kode, untuk memahami yang Anda harus berurusan dengan apa entitas itu. Ketikkan anotasi meningkatkan keterbacaan kode.
Jadi, apa yang telah dilakukan dengan Python untuk membawa kode ke tingkat keterbacaan yang sama yang membedakan kode yang ditulis dalam bahasa yang diketik secara statis?
Ketik Anotasi dengan Python
Sekarang kita siap untuk berbicara serius tentang mengetik anotasi dengan Python. Saat membaca program yang ditulis dengan Python 2, orang bisa melihat bahwa programmer menyediakan kode mereka dengan petunjuk memberitahu pembaca kode apa jenis variabel atau nilai yang dikembalikan oleh fungsi.
Kode serupa awalnya tampak seperti
ini :
users = []
Ketikkan anotasi yang digunakan untuk komentar sederhana. Tetapi kebetulan Python mulai bergeser ke arah cara yang lebih seragam dalam menangani anotasi. Secara khusus, kita berbicara tentang munculnya dokumen
PEP 3107 , yang didedikasikan untuk penjelasan fungsi.
Selanjutnya, pekerjaan dimulai pada
PEP 484 . Dokumen ini, yang dikhususkan untuk mengetik anotasi, dikembangkan dalam kaitan erat dengan mypy, proyek DropBox, yang bertujuan untuk memverifikasi jenis sebelum menjalankan skrip. Menggunakan mypy, perlu diingat bahwa pengecekan tipe tidak dilakukan selama eksekusi skrip. Pesan kesalahan dapat diterima saat runtime jika, misalnya, Anda mencoba membuat sesuatu dari tipe yang tidak didukung tipe ini. Katakan - jika Anda mencoba mengiris kamus atau memanggil metode
.pop()
untuk sebuah string.
Inilah yang dapat Anda pelajari dari PEP 484 tentang detail implementasi anotasi: “Meskipun anotasi ini tersedia pada saat dijalankan melalui atribut
annotations
biasa, tidak ada pemeriksaan tipe yang dilakukan pada saat run time. Sebagai gantinya, proposal ini menyediakan keberadaan alat pengecekan tipe mandiri yang terpisah, yang dengannya pengguna, jika diinginkan, dapat memeriksa kode sumber programnya. Secara umum, alat pengecekan tipe serupa bekerja seperti linter yang sangat kuat. "Meskipun, tentu saja, pengguna individu dapat menggunakan alat serupa untuk memeriksa jenis saat runtime, baik untuk penerapan metodologi Desain Dengan Kontrak atau untuk penerapan optimasi JIT. Tetapi harus dicatat bahwa alat tersebut belum mencapai kematangan yang memadai."
Bagaimana cara bekerja dengan anotasi jenis terlihat dalam praktik?
Misalnya, penggunaannya berarti kemampuan untuk memfasilitasi pekerjaan di berbagai IDE. Jadi,
PyCharm , penawaran, berdasarkan pada informasi jenis, penyelesaian kode dan verifikasi. Fitur serupa tersedia dalam Kode VS.
Jenis anotasi berguna karena satu alasan lagi: mereka melindungi pengembang dari kesalahan bodoh.
Ini adalah contoh bagus dari perlindungan semacam itu.
Misalkan kita menambahkan nama orang ke kamus:
names = {'Vicki': 'Boykis', 'Kim': 'Kardashian'} def append_name(dict, first_name, last_name): dict[first_name] = last_name append_name(names,'Kanye',9)
Jika kami mengizinkan ini, akan ada banyak entri yang salah dalam kamus.
Mari kita perbaiki ini:
from typing import Dict names_new: Dict[str, str] = {'Vicki': 'Boykis', 'Kim': 'Kardashian'} def append_name(dic: Dict[str, str] , first_name: str, last_name: str): dic[first_name] = last_name append_name(names_new,'Kanye',9.7) names_new
Sekarang periksa kode ini dengan mypy dan dapatkan yang berikut:
(kanye) mbp-vboykis:types vboykis$ mypy kanye.py kanye.py:9: error: Argument 3 to "append_name" has incompatible type "float"; expected "str"
Dapat dilihat bahwa mypy tidak memungkinkan Anda untuk menggunakan nomor di mana string diharapkan. Mereka yang ingin menggunakan tes seperti itu secara teratur disarankan untuk memasukkan mypy di mana pengujian kode dilakukan dalam sistem integrasi berkelanjutan mereka.
Ketik petunjuk dalam berbagai IDE
Salah satu manfaat paling penting dari menggunakan anotasi jenis adalah bahwa mereka memungkinkan programmer Python untuk menggunakan fitur penyelesaian kode yang sama di berbagai IDE yang tersedia untuk bahasa yang diketik secara statis.
Misalnya, Anda memiliki sepotong kode yang menyerupai yang berikut ini. Ini adalah beberapa fungsi dari contoh sebelumnya yang dibungkus dalam kelas.
from typing import Dict class rainfallRate: def __init__(self, hours, inches): self.hours= hours self.inches = inches def calculateRate(self, inches:int, hours:int) -> float: return inches/hours rainfallRate.calculateRate() class addNametoDict: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name self.dict = dict def append_name(dict:Dict[str, str], first_name:str, last_name:str): dict[first_name] = last_name addNametoDict.append_name()
Yang menyenangkan adalah bahwa kita, atas inisiatif kita sendiri, menambahkan deskripsi jenis ke kode, kita dapat mengamati apa yang terjadi dalam program ketika metode kelas dipanggil:
Tip Tipe IDEMemulai dengan anotasi jenis
Anda dapat menemukan rekomendasi yang bagus dalam dokumentasi untuk mypy mengenai apa yang harus dimulai ketika mulai mengetik basis kode:
- Mulai dari yang kecil - pastikan beberapa file yang berisi banyak anotasi divalidasi dengan mypy.
- Tulis skrip untuk menjalankan mypy. Ini akan membantu mencapai hasil tes yang konsisten.
- Jalankan mypy di pipa CI untuk mencegah kesalahan tipe.
- Secara bertahap beri catatan modul yang paling sering digunakan dalam proyek.
- Tambahkan jenis anotasi ke kode yang ada yang Anda modifikasi; lengkapi mereka dengan kode baru yang Anda tulis.
- Gunakan MonkeyType atau PyAnnotate untuk secara otomatis membubuhi keterangan kode lama.
Sebelum memulai anotasi kode Anda sendiri, akan berguna bagi Anda untuk berurusan dengan sesuatu.
Pertama, Anda perlu mengimpor modul
pengetikan ke dalam kode jika Anda menggunakan sesuatu selain string, integer, booleans, dan nilai-nilai tipe Python dasar lainnya.
Kedua, modul ini memungkinkan untuk bekerja dengan beberapa tipe kompleks. Diantaranya adalah
Dict
,
Tuple
,
List
dan
Set
. Konstruksi bentuk
Dict[str, float]
berarti Anda ingin bekerja dengan kamus yang elemennya menggunakan string sebagai kunci dan angka titik-mengambang sebagai nilai. Ada juga jenis yang disebut
Optional
dan
Union
.
Ketiga, Anda harus membiasakan diri dengan format anotasi jenis:
import typing def some_function(variable: type) -> return_type: do_something
Jika Anda ingin tahu lebih banyak tentang cara mulai menerapkan anotasi jenis dalam proyek Anda, saya ingin mencatat bahwa banyak tutorial yang bagus ditujukan untuk ini.
Ini salah satunya. Saya menganggap itu yang terbaik. Setelah menguasainya, Anda akan belajar tentang anotasi kode dan verifikasi.
Hasilnya. Apakah layak menggunakan anotasi jenis dengan Python?
Sekarang mari kita bertanya pada diri sendiri apakah Anda harus menggunakan anotasi ketik dengan Python. Sebenarnya, itu tergantung pada fitur proyek Anda. Inilah yang dikatakan Guido van Rossum dalam dokumentasi untuk mypy tentang ini: “Tujuan mypy bukan untuk meyakinkan semua orang untuk menulis kode Python yang diketik secara statis. Pengetikan statis sepenuhnya opsional sekarang dan di masa depan. Tujuan Mypy adalah memberi programmer Python lebih banyak opsi. Ini untuk membuat Python alternatif yang lebih kompetitif untuk bahasa yang diketik secara statis lain yang digunakan dalam proyek-proyek besar. Ini untuk meningkatkan produktivitas programmer dan meningkatkan kualitas perangkat lunak. "
Waktu yang diperlukan untuk mengonfigurasi mypy dan merencanakan jenis-jenis yang diperlukan untuk program tertentu tidak membenarkan dirinya dalam proyek-proyek kecil dan selama percobaan (misalnya, yang dilakukan di Jupyter). Proyek mana yang harus dianggap kecil? Mungkin yang volumenya, menurut perkiraan yang cermat, tidak melebihi 1000 baris.
Ketikkan anotasi masuk akal dalam proyek yang lebih besar. Di sana mereka dapat, khususnya, menghemat banyak waktu. Kita berbicara tentang proyek yang dikembangkan oleh kelompok pemrogram, tentang paket, tentang kode, yang digunakan dalam pengembangan sistem kontrol versi dan jaringan pipa CI.
Saya percaya bahwa anotasi jenis dalam beberapa tahun mendatang akan menjadi jauh lebih umum daripada sekarang, belum lagi fakta bahwa mereka mungkin berubah menjadi alat sehari-hari biasa. Dan saya percaya bahwa seseorang yang mulai bekerja dengan mereka sebelum yang lain tidak akan kehilangan apapun.
Pembaca yang budiman! Apakah Anda menggunakan anotasi jenis dalam proyek Python Anda?
