Kecuali saya salah, membuat fungsi dalam Python bekerja seperti ini:
def my_func(param1, param2):
# stuff
Namun, Anda tidak benar-benar memberikan jenis parameter tersebut. Juga, jika saya ingat, Python adalah bahasa yang sangat diketik, karena itu, sepertinya Python seharusnya tidak membiarkan Anda memasukkan parameter tipe yang berbeda dari yang diharapkan oleh pembuat fungsi. Namun, bagaimana Python tahu bahwa pengguna fungsi ini lewat jenis yang tepat? Apakah program hanya akan mati jika itu tipe yang salah, dengan asumsi fungsi tersebut benar-benar menggunakan parameter? Apakah Anda harus menentukan jenisnya?
python
function
parameters
Leif Andersen
sumber
sumber
Jawaban:
Python diketik dengan kuat karena setiap objek memiliki tipe, setiap objek tahu tipenya, tidak mungkin untuk secara tidak sengaja atau sengaja menggunakan objek tipe "seolah-olah" itu adalah objek dari tipe yang berbeda , dan semua operasi elementer pada objek adalah didelegasikan ke jenisnya.
Ini tidak ada hubungannya dengan nama . Sebuah nama dengan Python tidak "memiliki tipe": jika dan ketika suatu nama didefinisikan, nama tersebut merujuk pada suatu objek , dan objek tersebut memang memiliki suatu tipe (tetapi itu sebenarnya tidak memaksa suatu tipe pada nama : a nama adalah nama).
Sebuah nama dengan Python dapat dengan baik merujuk ke objek yang berbeda pada waktu yang berbeda (seperti dalam kebanyakan bahasa pemrograman, meskipun tidak semua) - dan tidak ada batasan pada nama sedemikian rupa, jika pernah merujuk ke objek tipe X, itu kemudian sampai selama-lamanya dibatasi untuk merujuk hanya untuk benda-benda lain dari jenis Kendala X. atas nama bukan bagian dari konsep "mengetik kuat", meskipun beberapa penggemar dari statis mengetik (di mana nama-nama yang bisa dibatasi, dan statis, AKA compile- waktu, fashion, juga) menyalahgunakan istilah dengan cara ini.
sumber
try
/except
) akan terjadi ketika dan jika operasi dicoba bahwa objek tidak mendukung. Dalam Python 3.5 Anda sekarang dapat secara opsional "menentukan jenis" dari argumen, tetapi tidak ada kesalahan, per se, jika spesifikasi dilanggar; notasi pengetikan hanya dimaksudkan untuk membantu alat terpisah yang melakukan analisis dll, itu tidak mengubah perilaku Python itu sendiri.Jawaban lain telah melakukan pekerjaan yang baik dalam menjelaskan mengetik bebek dan jawaban sederhana oleh tzot :
Namun , satu hal yang menarik telah berubah sejak 2010 (ketika pertanyaan pertama kali ditanyakan), yaitu implementasi PEP 3107 (diimplementasikan dalam Python 3). Anda sekarang dapat benar-benar menentukan jenis parameter dan jenis jenis pengembalian fungsi seperti ini:
Di sini kita dapat melihat bahwa
pick
dibutuhkan 2 parameter, daftarl
dan bilangan bulatindex
. Ini juga harus mengembalikan integer.Jadi di sini tersirat bahwa
l
adalah daftar bilangan bulat yang dapat kita lihat tanpa banyak usaha, tetapi untuk fungsi yang lebih kompleks dapat sedikit membingungkan mengenai apa yang harus dimasukkan dalam daftar. Kami juga ingin nilai defaultindex
menjadi 0. Untuk menyelesaikan ini, Anda dapat memilih untuk menulispick
seperti ini sebagai gantinya:Perhatikan bahwa kita sekarang memasukkan string sebagai tipe
l
, yang diizinkan secara sintaksis, tetapi tidak baik untuk parsing secara terprogram (yang akan kita bahas nanti).Penting untuk dicatat bahwa Python tidak akan menaikkan
TypeError
jika Anda melayangkan float ke dalamindex
, alasan untuk ini adalah salah satu poin utama dalam filosofi desain Python: "Kita semua menyetujui orang dewasa di sini" , yang berarti Anda diharapkan untuk Waspadai apa yang bisa Anda berikan ke suatu fungsi dan apa yang tidak bisa Anda lakukan. Jika Anda benar-benar ingin menulis kode yang melempar TypeErrors Anda dapat menggunakanisinstance
fungsi untuk memeriksa bahwa argumen yang dikirimkan adalah tipe yang tepat atau subkelasnya seperti ini:Lebih lanjut tentang mengapa Anda jarang melakukan ini dan apa yang harus Anda lakukan malah dibicarakan di bagian selanjutnya dan di komentar.
PEP 3107 tidak hanya meningkatkan keterbacaan kode tetapi juga memiliki beberapa kasus penggunaan pas yang dapat Anda baca di sini .
Jenis anotasi mendapat lebih banyak perhatian di Python 3.5 dengan pengenalan PEP 484 yang memperkenalkan modul standar untuk petunjuk jenis.
Petunjuk tipe ini berasal dari tipe checker mypy ( GitHub ), yang sekarang sesuai dengan PEP 484 .
Dengan modul pengetikan hadir dengan koleksi petunjuk jenis yang cukup komprehensif, termasuk:
List
,Tuple
,Set
,Map
- untuklist
,tuple
,set
danmap
masing-masing.Iterable
- berguna untuk generator.Any
- saat itu bisa apa saja.Union
- ketika itu bisa berupa apa saja di dalam set jenis tertentu, sebagai lawanAny
.Optional
- saat itu mungkin Tidak Ada. Singkatan untukUnion[T, None]
.TypeVar
- Digunakan dengan obat generik.Callable
- Digunakan terutama untuk fungsi, tetapi dapat digunakan untuk callable lainnya.Ini adalah petunjuk jenis yang paling umum. Daftar lengkap dapat ditemukan dalam dokumentasi untuk modul pengetikan .
Berikut ini adalah contoh lama menggunakan metode penjelasan yang diperkenalkan dalam modul pengetikan:
Salah satu fitur yang kuat adalah
Callable
yang memungkinkan Anda mengetik metode anotasi yang mengambil fungsi sebagai argumen. Sebagai contoh:Contoh di atas bisa menjadi lebih tepat dengan penggunaan
TypeVar
alih - alihAny
, tetapi ini telah dibiarkan sebagai latihan bagi pembaca karena saya yakin saya sudah mengisi jawaban saya dengan terlalu banyak informasi tentang fitur-fitur baru yang luar biasa yang diaktifkan dengan mengetikkan petunjuk.Sebelumnya ketika seseorang mendokumentasikan kode Python dengan Sphinx misalnya beberapa fungsi di atas dapat diperoleh dengan menulis dokumen yang diformat seperti ini:
Seperti yang Anda lihat, ini membutuhkan sejumlah baris tambahan (jumlah pastinya tergantung pada seberapa eksplisit Anda ingin menjadi dan bagaimana Anda memformat dokumen Anda). Tetapi sekarang harus jelas bagi Anda bagaimana PEP 3107 memberikan alternatif yang dalam banyak hal (semua?) Lebih unggul. Hal ini terutama berlaku dalam kombinasi dengan PEP 484 yang, seperti telah kita lihat, menyediakan modul standar yang mendefinisikan sintaks untuk jenis petunjuk / anotasi yang dapat digunakan sedemikian rupa sehingga tidak ambigu dan tepat namun fleksibel, membuat untuk kombinasi yang kuat.
Menurut pendapat pribadi saya, ini adalah salah satu fitur terbesar di Python. Saya tidak sabar menunggu orang mulai memanfaatkan kekuatannya. Maaf untuk jawaban yang panjang, tapi inilah yang terjadi ketika saya bersemangat.
Contoh kode Python yang banyak menggunakan tipe hinting dapat ditemukan di sini .
sumber
TypeError
, apa gunanya menggunakanpick(l: list, index: int) -> int
seperti mendefinisikan satu baris? Atau saya salah, saya tidak tahu.__annotations__
atribut objek fungsi).def f(a) -> Tuple[int, int]:
Anda tidak menentukan tipe. Metode ini hanya akan gagal (saat runtime) jika mencoba mengakses atribut yang tidak ditentukan pada parameter yang diteruskan.
Jadi fungsi sederhana ini:
... tidak akan gagal tidak peduli apa argumen yang dilewati.
Namun, fungsi ini:
... akan gagal saat runtime jika
param1
danparam2
keduanya tidak memiliki atribut yang dapat dipanggil bernamaquack
.sumber
Banyak bahasa memiliki variabel, yang merupakan tipe tertentu dan memiliki nilai. Python tidak memiliki variabel; memiliki objek, dan Anda menggunakan nama untuk merujuk ke objek-objek ini.
Dalam bahasa lain, saat Anda mengatakan:
kemudian variabel (biasanya integer) mengubah isinya ke nilai 1.
Dengan Python,
berarti “gunakan nama a untuk merujuk ke objek 1 ”. Anda dapat melakukan hal berikut dalam sesi Python interaktif:
Fungsi
type
ini disebut dengan objek1
; karena setiap objek tahu tipenya, mudah untuktype
mengetahui tipe kata dan mengembalikannya.Demikian juga, setiap kali Anda mendefinisikan suatu fungsi
fungsi menerima dua objek, dan menamainya ,
param1
danparam2
terlepas dari jenisnya. Jika Anda ingin memastikan objek yang diterima dari jenis tertentu, kode fungsi Anda seolah-olah mereka dari jenis yang diperlukan (s) dan menangkap pengecualian yang dilemparkan jika tidak. Pengecualian yang dilontarkan biasanyaTypeError
(Anda menggunakan operasi yang tidak valid) danAttributeError
(Anda mencoba mengakses anggota yang tidak ada (metode adalah anggota juga)).sumber
Python tidak diketik dalam arti pengecekan tipe statis atau waktu kompilasi.
Sebagian besar kode Python berada di bawah apa yang disebut "Bebek Mengetik" - misalnya, Anda mencari metode
read
pada objek - Anda tidak peduli jika objek tersebut adalah file pada disk atau soket, Anda hanya ingin membaca N byte darinya.sumber
Seperti yang dijelaskan Alex Martelli ,
Baca sisa jabatannya untuk informasi bermanfaat.
sumber
Python tidak peduli apa yang Anda berikan pada fungsinya. Saat Anda memanggil
my_func(a,b)
, variabel param1 dan param2 kemudian akan menyimpan nilai a dan b. Python tidak tahu bahwa Anda memanggil fungsi dengan tipe yang tepat, dan mengharapkan programmer untuk mengatasinya. Jika fungsi Anda akan dipanggil dengan berbagai jenis parameter, Anda dapat membungkus kode mengaksesnya dengan mencoba / kecuali blok dan mengevaluasi parameter dengan cara apa pun yang Anda inginkan.sumber
Anda tidak pernah menentukan jenisnya; Python memiliki konsep mengetik bebek ; pada dasarnya kode yang memproses parameter akan membuat asumsi tertentu tentang mereka - mungkin dengan memanggil metode tertentu yang diharapkan dapat diimplementasikan oleh parameter. Jika parameternya salah ketik, maka eksepsi akan dilempar.
Secara umum terserah pada kode Anda untuk memastikan bahwa Anda membagikan objek dengan tipe yang tepat - tidak ada kompiler yang menerapkan ini sebelumnya.
sumber
Ada satu pengecualian terkenal dari nilai ketikan-bebek yang disebutkan di halaman ini.
Ketika
str
fungsi memanggil__str__
metode kelas, secara halus pilih jenisnya:Seolah Guido memberi tahu kita pengecualian mana yang harus dimunculkan oleh suatu program jika menemui jenis yang tidak terduga.
sumber
Dalam Python semuanya memiliki tipe. Fungsi Python akan melakukan apa saja yang diminta untuk dilakukan jika jenis argumen mendukungnya.
Contoh:
foo
akan menambahkan semua yang bisa__add__
diedit;) tanpa perlu khawatir tentang jenisnya. Jadi itu berarti, untuk menghindari kegagalan, Anda harus menyediakan hanya hal-hal yang mendukung penambahan.sumber
Saya tidak melihat ini disebutkan dalam jawaban lain, jadi saya akan menambahkan ini ke pot.
Seperti yang orang lain katakan, Python tidak menerapkan tipe pada parameter fungsi atau metode. Diasumsikan bahwa Anda tahu apa yang Anda lakukan, dan bahwa jika Anda benar-benar perlu mengetahui jenis sesuatu yang disahkan, Anda akan memeriksanya dan memutuskan apa yang harus dilakukan untuk diri sendiri.
Salah satu alat utama untuk melakukan ini adalah fungsi isinstance ().
Sebagai contoh, jika saya menulis metode yang mengharapkan untuk mendapatkan data teks biner mentah, daripada string yang dikodekan utf-8 normal, saya bisa memeriksa jenis parameter dalam perjalanan dan baik beradaptasi dengan apa yang saya temukan, atau meningkatkan pengecualian untuk menolak.
Python juga menyediakan semua jenis alat untuk menggali objek. Jika Anda berani, Anda bahkan dapat menggunakan importlib untuk membuat objek sendiri dari kelas sewenang-wenang. Saya melakukan ini untuk membuat ulang objek dari data JSON. Hal seperti itu akan menjadi mimpi buruk dalam bahasa statis seperti C ++.
sumber
Untuk secara efektif menggunakan modul pengetikan (baru dengan Python 3.5) sertakan semua (
*
).Dan Anda akan siap untuk digunakan:
Namun, Anda masih bisa menggunakan nama jenis seperti
int
,list
,dict
, ...sumber
Saya telah menerapkan pembungkus jika ada yang ingin menentukan jenis variabel.
Gunakan sebagai:
EDIT
Kode di atas tidak berfungsi jika salah satu tipe argumen (atau return) tidak dinyatakan. Hasil edit berikut dapat membantu, di sisi lain, ini hanya berfungsi untuk kwargs dan tidak memeriksa argumen.
sumber