Menjelajahi kedalaman anotasi jenis dengan Python. Bagian 1

Sejak 2014, ketika Python memperkenalkan dukungan untuk anotasi tipe , programmer telah mengerjakan implementasinya dalam kode mereka. Penulis bahan, bagian pertama dari terjemahan yang kami terbitkan hari ini, mengatakan bahwa menurut penilaiannya, cukup berani, sekarang ketik anotasi (kadang-kadang disebut "petunjuk") digunakan dalam sekitar 20-30% dari kode yang ditulis dengan Python 3. Berikut adalah hasil survei, yang dia, pada Mei 2019, diposting di Twitter.

Ternyata, anotasi digunakan oleh 29% responden. Menurut penulis artikel tersebut, dalam beberapa tahun terakhir, ia semakin sering menemukan anotasi jenis di berbagai buku dan panduan belajar.

Bagian kedua



Dalam dokumentasi Python, istilah “ketik hint” dan “type annotation” digunakan secara bergantian. Penulis artikel ini terutama menggunakan istilah "type hint", kami menggunakan istilah "type annotation".

Artikel ini akan membahas berbagai masalah terkait penggunaan anotasi jenis dengan Python. Jika Anda ingin mendiskusikan artikel asli dengan penulis, Anda dapat menggunakan mekanisme tarik-permintaan .

Pendahuluan


Di sini Anda dapat menemukan contoh klasik bagaimana kode ditulis menggunakan anotasi jenis.

Ini kode reguler:

def greeting(name):     return 'Hello ' + name 

Berikut adalah kode tempat anotasi ditambahkan:

 def greeting(name: str) -> str:    return 'Hello ' + name 

Templat yang dengannya kode dengan anotasi jenis dieksekusi terlihat seperti ini:

 def function(variable: input_type) -> return_type:    pass 

Sekilas, tampaknya menerapkan anotasi jenis dalam kode terlihat sederhana dan mudah. Tetapi masih ada cukup banyak ketidakpastian dalam komunitas pengembang dalam memahami apa sebenarnya jenis anotasi itu. Selain itu, bahkan ada ambiguitas dalam cara memanggil mereka dengan benar - "anotasi" atau "petunjuk", dan dalam keuntungan apa yang diberikan oleh penggunaannya dalam basis kode.

Ketika saya mulai meneliti topik ini dan berpikir apakah saya perlu menggunakan anotasi jenis, saya merasa sangat bingung. Akibatnya, saya memutuskan untuk melakukan hal yang sama seperti yang selalu saya lakukan, setelah bertemu dengan sesuatu yang tidak dapat dipahami. Saya memutuskan untuk meneliti masalah ini secara mendalam dan memulai penelitian saya dalam bentuk materi ini, yang, saya harap, akan bermanfaat bagi mereka yang, seperti saya, ingin berurusan dengan anotasi jenis dengan Python.

Bagaimana komputer menjalankan program kami?


Untuk memahami apa yang ingin dicapai oleh pengembang Python dengan mengetikkan anotasi, mari kita bicara tentang mekanisme sistem komputer yang beberapa level di bawah kode Python. Berkat ini, kita dapat lebih memahami bagaimana, secara umum, komputer dan bahasa pemrograman bekerja.

Bahasa pemrograman, pada intinya, adalah alat yang memungkinkan Anda untuk memproses data menggunakan central processing unit (CPU), serta menyimpan dalam memori data yang perlu diproses dan data yang dihasilkan dari pemrosesan.


Sirkuit komputer yang disederhanakan

Sebuah prosesor adalah hal yang sangat bodoh pada intinya. Dia mampu melakukan tindakan yang mengesankan dengan data, tetapi dia hanya memahami instruksi mesin, yang mendidih hingga set sinyal listrik. Bahasa mesin dapat direpresentasikan sebagai terdiri dari nol dan satu.
Untuk menyiapkan angka-angka nol ini dan yang dipahami oleh prosesor, Anda perlu menerjemahkan kode dari bahasa tingkat tinggi ke bahasa tingkat rendah. Di sinilah kompiler dan interpreter masuk.

Jika bahasa dikompilasi atau dieksekusi (kode Python dijalankan melalui juru bahasa), maka kode dalam bahasa ini berubah menjadi kode mesin tingkat rendah yang berisi instruksi untuk komponen komputer tingkat rendah, yaitu untuk perangkat keras.

Ada beberapa cara untuk menerjemahkan kode yang ditulis dalam beberapa bahasa pemrograman ke dalam kode yang dapat dimengerti mesin. Anda dapat membuat file dengan kode program dan mengonversinya menjadi kode mesin menggunakan kompiler (ini adalah cara kerja C ++, Go, Rust dan beberapa bahasa lainnya), atau menjalankan kode secara langsung menggunakan penerjemah, yang akan bertanggung jawab untuk mengubah kode menjadi perintah mesin. Itulah caranya, dengan bantuan penerjemah, program-program dengan Python diluncurkan, serta dalam bahasa "scripting" lainnya, seperti PHP dan Ruby.


Skema pemrosesan kode bahasa yang ditafsirkan

Bagaimana perangkat keras tahu cara menyimpan nol dan yang mewakili data yang bekerja dengan program dalam memori? Program kami harus memberi tahu komputer bagaimana mengalokasikan memori untuk data ini. Dan apakah data ini? Itu tergantung pada jenis data apa yang didukung oleh bahasa tertentu.

Jenis data tersedia dalam semua bahasa. Biasanya, tipe data adalah salah satu topik pertama yang dipelajari pemula untuk belajar pemrograman dalam bahasa tertentu.

Ada tutorial yang sangat baik tentang Python yang sama, misalnya - ini adalah tempat Anda dapat menemukan informasi terperinci tentang tipe data. Dengan kata sederhana, tipe data adalah cara berbeda untuk merepresentasikan data yang disimpan dalam memori.

Di antara tipe data yang ada, misalnya, string dan integer dapat dicatat. Set tipe data yang tersedia untuk pengembang tergantung pada bahasa pemrograman yang mereka gunakan. Di sini, misalnya, adalah daftar tipe data Python dasar :

 int, float, complex str bytes tuple frozenset bool array bytearray list set dict 

Ada tipe data yang terdiri dari tipe data lainnya. Misalnya, daftar dengan Python dapat menyimpan bilangan bulat atau string, serta keduanya.

Untuk mengetahui berapa banyak memori yang perlu Anda alokasikan untuk menyimpan beberapa data, komputer perlu tahu tentang jenis data apa yang akan ditempatkan dalam memori. Python memiliki fungsi getsizeof yang akan memberi tahu kami tentang jumlah memori, yang dinyatakan dalam byte, yang diperlukan untuk menyimpan nilai berbagai tipe data.

Berikut adalah satu jawaban yang bagus untuk StackOverflow di mana Anda dapat menemukan informasi tentang cara mengetahui ukuran nilai "minimum" yang dapat disimpan dalam berbagai jenis variabel.

 import sys import decimal import operator d = {"int": 0,    "float": 0.0,    "dict": dict(),    "set": set(),    "tuple": tuple(),    "list": list(),    "str": "a",    "unicode": u"a",    "decimal": decimal.Decimal(0),    "object": object(), } #   ,        d_size = {} for k, v in sorted(d.items()):    d_size[k]=sys.getsizeof(v) sorted_x = sorted(d_size.items(), key=lambda kv: kv[1]) sorted_x [('object', 16), ('float', 24), ('int', 24), ('tuple', 48), ('str', 50), ('unicode', 50), ('list', 64), ('decimal', 104), ('set', 224), ('dict', 240)] 

Akibatnya, dengan menyortir kamus yang berisi sampel nilai dari berbagai jenis, kita dapat mengetahui bahwa ukuran maksimumnya adalah kamus kosong ( dict ) dan diikuti oleh satu set ( set ). Dibandingkan dengan mereka, sangat sedikit ruang yang dibutuhkan untuk menyimpan satu integer (tipe int ).

Contoh di atas memberi kita gambaran tentang berapa banyak memori yang diperlukan untuk menyimpan berbagai nilai yang digunakan dalam program.

Kenapa ini harus mengganggu kita? Faktanya adalah bahwa beberapa jenis lebih baik daripada yang lain untuk memecahkan beberapa masalah, memungkinkan Anda untuk memecahkan masalah ini lebih efektif. Dalam beberapa situasi, jenis harus diperiksa dengan cermat. Misalnya, kadang-kadang dilakukan pengecekan bahwa tipe data yang digunakan dalam program tidak bertentangan dengan beberapa asumsi yang dibuat saat merancang program.

Tetapi apakah tipe-tipe ini? Mengapa kita membutuhkannya? Di sinilah konsep "sistem tipe" berperan.

Pengantar Sistem Tipe


Dahulu kala , di galaksi yang jauh, orang-orang yang melakukan perhitungan matematis secara manual menyadari bahwa jika mereka membandingkan "tipe" dengan angka atau elemen persamaan, mereka bisa mengurangi jumlah kesalahan logis yang muncul ketika mendapatkan bukti matematis tentang elemen-elemen ini.

Karena pada mulanya ilmu komputer direduksi, pada intinya, pada pelaksanaan volume besar perhitungan manual, beberapa prinsip lama dipindahkan ke perhitungan ini. Tipe sistem telah menjadi alat yang digunakan untuk mengurangi jumlah kesalahan dalam program dengan menetapkan tipe yang sesuai untuk berbagai variabel atau elemen.

Berikut ini beberapa contohnya:

  • Jika kami menulis perangkat lunak untuk bank, maka kami tidak dapat menggunakan baris dalam fragmen kode yang menghitung saldo pada akun orang lain.
  • Jika kita bekerja dengan data survei dan ingin memahami apakah seseorang menjawab positif atau negatif terhadap suatu pertanyaan, maka jawaban "ya" dan "tidak" akan dikodekan secara alami menggunakan tipe logis.
  • Saat mengembangkan mesin pencari besar, kita harus membatasi jumlah karakter yang dapat dimasukkan oleh pengguna sistem ini di bidang permintaan pencarian. Ini berarti bahwa kita perlu memeriksa beberapa data string untuk kesesuaian dengan parameter tertentu.

Saat ini dalam pemrograman, ada dua sistem tipe utama. Inilah yang ditulis Steve Klabnik tentang ini: “Sistem tipe statis adalah mekanisme di mana kompiler memeriksa kode sumber dan memberikan label (disebut“ tipe ”) ke fragmen program, dan kemudian menggunakannya untuk menarik kesimpulan tentang perilaku program. Sistem tipe dinamis adalah mekanisme di mana kompiler menghasilkan kode untuk mengamati tipe data apa (mereka juga disebut "tipe", secara kebetulan) digunakan oleh program. "

Apa artinya ini? Ini berarti bahwa ketika bekerja dengan bahasa yang dikompilasi, Anda biasanya perlu menetapkan jenis entitas terlebih dahulu. Berkat ini, kompiler akan dapat memeriksanya selama kompilasi kode dan mencari tahu apakah mungkin untuk membuat program yang bermakna dari kode sumber yang disediakan untuk itu.

Baru-baru ini saya menemukan satu penjelasan tentang perbedaan antara pengetikan statis dan dinamis. Ini mungkin teks terbaik yang pernah saya baca tentang subjek ini. Ini adalah bagiannya: “Saya dulu menggunakan bahasa yang diketik secara statis, tetapi selama beberapa tahun terakhir saya telah memprogram terutama dengan Python. Pada awalnya, menggunakan pengetikan statis sedikit mengganggu saya. Ada perasaan bahwa kebutuhan untuk mendeklarasikan tipe variabel melambat dan memaksa saya untuk mengekspresikan ide-ide saya secara berlebihan. Python membiarkan saya melakukan apa yang saya inginkan, bahkan jika saya tidak sengaja melakukan sesuatu yang salah. Menggunakan bahasa dengan pengetikan statis seperti memberikan tugas kepada seseorang yang selalu bertanya lagi, mengklarifikasi detail kecil dari kasus yang ditugaskan kepadanya untuk diselesaikan. Pengetikan dinamis adalah saat orang yang diberi tugas selalu mengangguk setuju. Dalam hal ini, ada perasaan bahwa dia mengerti Anda. Tetapi kadang-kadang tidak ada kepastian yang lengkap bahwa orang yang kepadanya tugas itu diberikan telah dengan tepat mengetahui apa yang diharapkan darinya. ”

Dalam berbicara tentang sistem tipe, saya menemukan sesuatu yang saya tidak segera mengerti. Yaitu, konsep "pengetikan statis" dan "pengetikan dinamis" terkait erat dengan konsep "bahasa terkompilasi" dan "bahasa yang ditafsirkan", tetapi istilah "statis" dan "dikompilasi", serta istilah "dinamis" dan "ditafsirkan" bukan sinonim . Bahasa dapat diketik secara dinamis, seperti Python, dan pada saat yang sama dikompilasi. Demikian pula, suatu bahasa dapat diketik secara statis, seperti Java, tetapi juga ditafsirkan (misalnya, dalam kasus Jawa, saat menggunakan Java REPL).

Perbandingan tipe data dalam bahasa yang diketik secara statis dan dinamis


Apa perbedaan antara tipe data dalam bahasa yang diketik secara statis dan dinamis?

Saat menggunakan pengetikan statis, jenis harus dideklarasikan terlebih dahulu. Misalnya, jika Anda bekerja di Jawa, maka program Anda akan terlihat seperti ini:

 public class CreatingVariables {  public static void main(String[] args) {    int x, y, age, height;    double seconds, rainfall;    x = 10;    y = 400;    age = 39;    height = 63;    seconds = 4.71;    rainfall = 23;    double rate = calculateRainfallRate(seconds, rainfall);   } private static double calculateRainfallRate(double seconds, double rainfall) {  return rainfall/seconds; } 

Perhatikan awal program. Beberapa variabel dideklarasikan di sana, di sebelahnya terdapat indikasi jenis-jenis variabel ini:

 int x, y, age, height; double seconds, rainfall; 

Selain itu, jenis ditentukan baik ketika mendeklarasikan fungsi dan menyatakan argumen mereka. Tanpa deklarasi tipe ini, program tidak dapat dikompilasi. Saat membuat program Java, sejak awal, Anda perlu merencanakan jenis apa yang dimiliki entitas ini atau yang dimiliki. Akibatnya, kompiler, saat memproses kode program-program tersebut, akan tahu apa sebenarnya yang perlu diperiksa dalam proses menghasilkan kode mesin.

Python menghilangkan kerumitan seorang programmer. Kode Python serupa mungkin terlihat seperti ini:

 y = 400 age = 39 height = 63 seconds = 4.71 rainfall = 23 rate = calculateRainfall(seconds, rainfall) def calculateRainfall(seconds, rainfall):  return rainfall/seconds 

Bagaimana semua ini bekerja di perut Python? Dilanjutkan ...

Pembaca yang budiman! Bahasa pemrograman mana yang Anda gunakan meninggalkan kesan paling menyenangkan?

Source: https://habr.com/ru/post/id463929/


All Articles