Selamat siang teman Dan kami terus meningkatkan intensitas peluncuran kursus baru dan sekarang dengan senang hati mengumumkan bahwa kelas-kelas di kursus
"Web-developer in Python" akan dimulai pada akhir April. Dalam hal ini, kami secara tradisional membagikan terjemahan materi yang bermanfaat. Mari kita mulai.
Python dikenal sebagai bahasa pengetikan yang dinamis. Sangat mudah untuk menulis kerangka kerja DSL yang sulit diurai dengan alat pemeriksaan tipe statis. Meskipun demikian, dengan inovasi fungsional terbaru
mypy , seperti
protokol dan
tipe literal , serta dukungan dasar untuk dukungan metaclasses dan deskriptor, kita sering dapat mendapatkan jenis yang tepat, tetapi masih sulit untuk menghindari positif palsu dan faktor negatif lainnya. Untuk mengatasi masalah ini dan menghindari kebutuhan untuk menyesuaikan sistem tipe untuk setiap kerangka kerja,
mypy mendukung sistem
plug-in . Plugin adalah modul dalam Python yang menyediakan kait plugin yang akan dipanggil
mypy saat memeriksa jenis kelas dan fungsi yang berinteraksi dengan pustaka atau kerangka kerja. Dengan demikian, dimungkinkan untuk lebih akurat membedakan jenis fungsi yang dikembalikan, yang sebaliknya sangat sulit untuk diungkapkan, atau secara otomatis menghasilkan beberapa metode kelas untuk mencerminkan efek dari dekorator. Untuk mempelajari lebih lanjut tentang arsitektur sistem plug-in dan melihat daftar lengkap fitur, lihat
dokumentasi .
Plugin terkait untuk pustaka standarMypy hadir dengan plugin default untuk mengimplementasikan fungsi dasar dan kelas, serta
dataclasses
ctypes
,
contextlib
dan
dataclasses
. Ini juga termasuk plugin untuk
attrs
(secara historis telah menjadi plugin pihak ketiga pertama yang ditulis untuk
mypy ). Plugin ini memungkinkan
mypy untuk lebih akurat menentukan jenis dan dengan benar memeriksa kode untuk jenis menggunakan fungsi pustaka ini. Untuk menunjukkan ini dengan contoh, lihat cuplikan kode:
from dataclasses import dataclass from typing import Generic, TypeVar @dataclass class TaggedVector(Generic[T]): data: List[T] tag: str position = TaggedVector([0, 0, 0], 'origin')
Di atas,
get_class_decorator_hook()
dipanggil ketika kelas didefinisikan. Ini menambahkan metode yang dibuat secara otomatis, termasuk
__init__()
, ke badan fungsi.
Mypy menggunakan konstruktor semacam itu untuk menghitung
TaggedVector[int]
sebagai tipe untuk
position
. Seperti yang Anda lihat dari contoh, plugin berfungsi bahkan dengan kelas generik.
Berikut ini sepotong kode lainnya:
from contextlib import contextmanager @contextmanager def timer(title: str) -> Iterator[float]: ... with timer(9000) as tm: ...
Di sini
get_function_hook()
memberikan jenis pengembalian yang tepat untuk dekorator
get_function_hook()
, sehingga panggilan ke fungsi yang didekorasi dapat diperiksa untuk kesesuaian dengan jenis tertentu. Sekarang
mypy dapat mengenali kesalahan: argumen untuk
timer()
harus berupa string.
Kombinasi plugin dan bertopikSelain menggunakan fungsi Python dinamis, kerangka kerja sering mengalami masalah memiliki API besar.
Mypy membutuhkan file
rintisan untuk pustaka untuk menguji kode yang menggunakan pustaka ini (hanya jika pustaka tidak berisi anotasi bawaan, yang tidak begitu umum). Mendistribusikan rintisan untuk kerangka kerja besar dengan
typeshed bukanlah praktik yang umum:
- Typeshed memiliki siklus rilis yang relatif lambat (dikirimkan bersama mypy ).
- Rintisan yang tidak lengkap dapat menyebabkan panggilan palsu, yang akan sangat sulit untuk dihindari.
- Jangan hanya mencampur bertopik dari versi pengetik berbeda.
Paket rintisan yang diperkenalkan dalam
PEP 561 melakukan hal berikut:
- Pengembang dapat merilis paket rintisan sesering yang mereka inginkan.
- Pengguna yang belum memilih untuk menggunakan paket tidak akan melihat positif palsu.
- Anda dapat dengan aman menginstal versi acak dari beberapa paket rintisan yang berbeda.
Selain itu,
pip
memungkinkan Anda untuk menggabungkan berbagai tulisan rintisan untuk perpustakaan dan plugin
mypy yang sesuai ke dalam satu distribusi. Rintisan untuk kerangka
mypy atau plugin yang sesuai dapat dengan mudah dikembangkan dan disatukan menjadi satu distribusi, yang sangat berguna karena plugin mengisi definisi yang hilang atau tidak akurat dalam rintisan.
Contoh terakhir dari paket tersebut adalah
SQLAlchemy stubs and plugin , dengan rilis publik pertama versi 0.1, yang diterbitkan beberapa waktu lalu di PyPI. Terlepas dari kenyataan bahwa proyek ini dalam versi Alpha awal, kita dapat menggunakannya dengan aman di DropBox untuk meningkatkan pemeriksaan tipe. Plugin memahami deklarasi ORM dasar:
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String)
Dalam cuplikan kode di atas, plugin menggunakan
get_dynamic_class_hook()
untuk memberi tahu
mypy bahwa Base adalah kelas dasar yang valid, bahkan jika itu tidak terlihat seperti itu. Kemudian
get_base_class_hook()
dipanggil untuk mendefinisikan Pengguna, dan menambahkan beberapa atribut yang dibuat secara otomatis. Selanjutnya, kami membuat instance dari model:
user = User(id=42, name=42)
get_function_hook()
dipanggil, jadi
mypy dapat mengindikasikan kesalahan: nilai
integer
diterima sebagai ganti nama pengguna.
Rintisan bertopik mendefinisikan
Column
sebagai deskriptor
generik , sehingga atribut model mendapatkan tipe yang benar:
id_col = User.id
Kami menyambut PR yang menambahkan tipe yang lebih tepat ke bertopik (kemajuan untuk modul inti dilacak di
sini ).
Berikut adalah beberapa jebakan yang kami temukan saat mengerjakan colokan:
- Gunakan
__getattr__()
untuk menghindari kesalahan positif pada tahap awal ketika stubs tidak selesai (ini mencegah kesalahan mypy jika atribut modul hilang). Anda juga dapat menggunakan ini dalam file __init__.py
jika ada submodula yang hilang. - Deskriptor sering membantu dengan definisi tipe yang lebih akurat untuk akses atribut khusus (seperti pada contoh Kolom yang kami ulas di atas). Menggunakan deskriptor baik-baik saja bahkan jika implementasi aktual runtime menggunakan mekanisme yang lebih kompleks, termasuk metaclass, misalnya.
- Tanpa ragu, nyatakan kelas kerangka kerja sebagai digeneralisasi. Terlepas dari kenyataan bahwa mereka tidak seperti saat runtime, teknik ini memungkinkan Anda untuk lebih akurat menentukan jenis beberapa elemen kerangka kerja, sementara kesalahan runtime dapat dengan mudah dielakkan . (Kami berharap bahwa kerangka kerja akan secara bertahap menambahkan dukungan
typing.Generic
untuk tipe generik, secara eksplisit mewarisi kelas yang sesuai dari typing.Generic
. typing.Generic
.)
Plugin mypy baru-baru ini dirilisSudah ada beberapa plugin yang tersedia untuk kerangka kerja Python populer. Terlepas dari plugin
SQLAlchemy yang disebutkan di atas, paket sampel penting lainnya dengan bertopik dan plugin
mypy built-in termasuk bertopik untuk antarmuka
Django dan
Zope . Pekerjaan aktif sedang berlangsung pada proyek-proyek ini.
Menginstal dan menghubungkan paket rintisan dan pluginGunakan pip untuk menginstal paket plugin untuk
mypy dan / atau rintisan ke lingkungan virtual di mana
mypy sudah
diinstal :
$ pip install sqlalchemy-stubs
Mypy akan secara otomatis mendeteksi bertopik yang diinstal. Untuk menghubungkan plugin yang diinstal, sertakan langsung di mypy.ini (atau dalam file konfigurasi pengguna):
[mypy] plugins = sqlmypy, mypy_django_plugin.main
Mengembangkan plugin
mypy dan menulis tulisan rintisan
Jika Anda ingin mengembangkan paket stubs dan plugins untuk kerangka kerja yang Anda gunakan, kita bisa menggunakan
repositori sqlalchemy-stubs sebagai templat. Ini termasuk
setup.py
, pengujian infrastruktur menggunakan tes berbasis data, dan contoh kelas plug-in dengan satu set kait untuk plug-in (kait plugin). Kami merekomendasikan menggunakan
stubgen untuk secara otomatis menghasilkan
stubgen yang datang dengan
mypy untuk mulai menggunakannya.
Stubgen
telah
mypy 0.670
meningkat di
mypy 0.670
.
Periksa
dokumentasi jika Anda ingin tahu lebih banyak tentang
sistem plugin
mypy . Anda juga dapat mencari kode sumber plugin yang dibahas di artikel di Internet. Jika Anda memiliki pertanyaan, Anda dapat menanyakannya di
sini .
15 April akan menjadi
webinar terbuka gratis di lapangan, yang akan diselenggarakan oleh salah satu penyelenggara komunitas Python Moskow -
Vladimir Filonov , mendaftar, itu akan menarik. Dan sekarang kami menunggu komentar Anda tentang materi yang diterjemahkan.