Beberapa debugger untuk Python dijelaskan di bawah ini, dan fungsi bawaannya memungkinkan Anda untuk masuk ke salah satunya Show Modul pdb adalah debugger mode konsol yang sederhana namun memadai untuk Python. Ini adalah bagian dari pustaka Python standar, dan memang demikian. Anda juga dapat menulis debugger Anda sendiri dengan menggunakan kode untuk pdb sebagai contoh Lingkungan pengembangan interaktif IDLE, yang merupakan bagian dari distribusi Python standar (biasanya tersedia sebagai Alat/skrip/idle3), menyertakan debugger grafis PythonWin adalah IDE Python yang menyertakan debugger GUI berdasarkan pdb. Warna debugger PythonWin breakpoints dan memiliki beberapa fitur keren seperti debugging program non-PythonWin. PythonWin tersedia sebagai bagian dari proyek pywin32 dan sebagai bagian dari distribusi ActivePython Eric adalah IDE yang dibangun di atas PyQt dan komponen pengeditan Scintilla trepan3k adalah debugger mirip gdb Visual Studio Code adalah IDE dengan alat debugging yang terintegrasi dengan perangkat lunak kontrol versi Ada sejumlah IDE Python komersial yang menyertakan debugger grafis. Mereka termasuk
Ya Pylint dan Pyflakes melakukan pemeriksaan dasar yang akan membantu Anda menemukan bug lebih cepat Pemeriksa tipe statis seperti Mypy, Pyre, dan Pytype dapat memeriksa petunjuk tipe dalam kode sumber Python Anda tidak memerlukan kemampuan untuk mengkompilasi kode Python ke C jika yang Anda inginkan adalah program yang berdiri sendiri yang dapat diunduh dan dijalankan oleh pengguna tanpa harus menginstal distribusi Python terlebih dahulu. Ada sejumlah alat yang menentukan kumpulan modul yang diperlukan oleh suatu program dan mengikat modul-modul ini bersama-sama dengan biner Python untuk menghasilkan satu modul yang dapat dieksekusi. Salah satunya adalah dengan menggunakan alat freeze, yang termasuk dalam pohon sumber Python sebagai Tools/freeze. Itu mengubah kode byte Python ke array C; Ini bekerja dengan memindai sumber Anda secara rekursif untuk pernyataan impor (dalam kedua bentuk) dan mencari modul di jalur Python standar serta di direktori sumber (untuk modul bawaan). Ini kemudian mengubah bytecode untuk modul yang ditulis dengan Python menjadi kode C (penginisialisasi array yang dapat diubah menjadi objek kode menggunakan modul marshal) dan membuat file konfigurasi yang dibuat khusus yang hanya berisi modul bawaan yang benar-benar digunakan dalam . Itu kemudian mengkompilasi kode C yang dihasilkan dan menautkannya dengan juru bahasa Python lainnya untuk membentuk biner mandiri yang bertindak persis seperti skrip Anda Paket-paket berikut dapat membantu pembuatan konsol dan GUI yang dapat dieksekusi
Ya. Gaya pengkodean yang diperlukan untuk modul perpustakaan standar didokumentasikan sebagai PEP 8 Ini bisa menjadi kejutan untuk mendapatkan kode yang sebelumnya berfungsi ketika dimodifikasi dengan menambahkan pernyataan penugasan di suatu tempat di badan fungsi Kode ini >>> x = 10 >>> def bar(): .. print(x) ... >>> bar() 10 bekerja, tapi kode ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_ menghasilkan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_22 >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment Ini karena ketika Anda membuat tugas ke variabel dalam lingkup, variabel tersebut menjadi lokal untuk lingkup tersebut dan membayangi variabel bernama serupa di lingkup luar. Karena pernyataan terakhir di foo menetapkan nilai baru ke >>> x = 10 >>> def foo(): .. print(x) .. x += 124, kompiler mengenalinya sebagai variabel lokal. Akibatnya ketika >>> x = 10 >>> def foo(): .. print(x) .. x += 125 sebelumnya mencoba untuk mencetak variabel lokal yang tidak diinisialisasi dan hasil kesalahan Dalam contoh di atas, Anda dapat mengakses variabel lingkup luar dengan mendeklarasikannya secara global >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_ Deklarasi eksplisit ini diperlukan untuk mengingatkan Anda bahwa (tidak seperti situasi analog yang dangkal dengan kelas dan variabel instan) Anda sebenarnya mengubah nilai variabel di lingkup luar >>> print(x) 11 Anda dapat melakukan hal serupa dalam lingkup bersarang menggunakan kata kunci >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_ Dalam Python, variabel yang hanya direferensikan di dalam suatu fungsi bersifat global secara implisit. Jika sebuah variabel diberi nilai di mana saja di dalam badan fungsi, itu dianggap sebagai lokal kecuali secara eksplisit dinyatakan sebagai global Meskipun agak mengejutkan pada awalnya, pertimbangan sesaat menjelaskan hal ini. Di satu sisi, mensyaratkan variabel yang ditetapkan memberikan batasan terhadap efek samping yang tidak diinginkan. Di sisi lain, jika >>> x = 10 >>> def foo(): .. print(x) .. x += 127 diperlukan untuk semua referensi global, Anda akan selalu menggunakan >>> x = 10 >>> def foo(): .. print(x) .. x += 127. Anda harus mendeklarasikan sebagai global setiap referensi ke fungsi bawaan atau ke komponen modul yang diimpor. Kekacauan ini akan mengalahkan kegunaan deklarasi >>> x = 10 >>> def foo(): .. print(x) .. x += 127 untuk mengidentifikasi efek samping Asumsikan Anda menggunakan for loop untuk mendefinisikan beberapa lambda yang berbeda (atau bahkan fungsi biasa), mis. g >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2) Ini memberi Anda daftar yang berisi 5 lambda yang menghitung >>> x = 10 >>> def foo(): .. print(x) .. x += 131. Anda mungkin berharap bahwa, ketika dipanggil, mereka akan kembali, masing-masing, >>> x = 10 >>> def foo(): .. print(x) .. x += 132, >>> x = 10 >>> def foo(): .. print(x) .. x += 133, >>> x = 10 >>> def foo(): .. print(x) .. x += 134, >>> x = 10 >>> def foo(): .. print(x) .. x += 135, dan >>> x = 10 >>> def foo(): .. print(x) .. x += 136. Namun, ketika Anda benar-benar mencoba, Anda akan melihat bahwa semuanya kembali >>> x = 10 >>> def foo(): .. print(x) .. x += 136 >>> squares[2]() 16 >>> squares[4]() 16 Hal ini terjadi karena >>> x = 10 >>> def foo(): .. print(x) .. x += 124 tidak bersifat lokal untuk lambda, tetapi didefinisikan di lingkup luar, dan diakses saat lambda dipanggil — bukan saat didefinisikan. Di akhir perulangan, nilai >>> x = 10 >>> def foo(): .. print(x) .. x += 124 adalah >>> x = 10 >>> def foo(): .. print(x) .. x += 134, jadi semua fungsi sekarang mengembalikan >>> x = 10 >>> def foo(): .. print(x) .. x += 141, i. e. >>> x = 10 >>> def foo(): .. print(x) .. x += 1_36. Anda juga dapat memverifikasi ini dengan mengubah nilai >>> x = 10 >>> def foo(): .. print(x) .. x += 124 dan melihat bagaimana hasil lambdas berubah >>> x = 8 >>> squares[2]() 64 Untuk menghindari hal ini, Anda perlu menyimpan nilai dalam variabel lokal ke lambda, sehingga mereka tidak bergantung pada nilai global >>> x = 10 >>> def foo(): .. print(x) .. x += 124 >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2) Di sini, >>> x = 10 >>> def foo(): .. print(x) .. x += 1_45 membuat variabel baru >>> x = 10 >>> def foo(): .. print(x) .. x += 146 lokal ke lambda dan dihitung ketika lambda didefinisikan sehingga memiliki nilai yang sama dengan yang dimiliki >>> x = 10 >>> def foo(): .. print(x) .. x += 124 pada saat itu di loop. Artinya, nilai >>> x = 10 >>> def foo(): .. print(x) .. x += 1_46 akan menjadi >>> x = 10 >>> def foo(): .. print(x) .. x += 132 di lambda pertama, >>> x = 10 >>> def foo(): .. print(x) .. x += 133 di lambda kedua, >>> x = 10 >>> def foo(): .. print(x) .. x += 151 di lambda ketiga, dan seterusnya. Oleh karena itu setiap lambda sekarang akan mengembalikan hasil yang benar >>> x = 10 >>> def foo(): .. print(x) .. x += 1_0 Perhatikan bahwa perilaku ini tidak khusus untuk lambda, tetapi juga berlaku untuk fungsi reguler Cara kanonik untuk berbagi informasi lintas modul dalam satu program adalah dengan membuat modul khusus (sering disebut config atau cfg). Cukup impor modul konfigurasi di semua modul aplikasi Anda; . Karena hanya ada satu instance dari setiap modul, setiap perubahan yang dibuat pada objek modul akan tercermin di mana-mana. Sebagai contoh config. py >>> x = 10 >>> def foo(): .. print(x) .. x += 1_1 mod. py >>> x = 10 >>> def foo(): .. print(x) .. x += 1_2 utama. py >>> x = 10 >>> def foo(): .. print(x) .. x += 1_3 Perhatikan bahwa menggunakan modul juga merupakan dasar untuk mengimplementasikan pola desain singleton, untuk alasan yang sama Secara umum, jangan gunakan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_52. Melakukan hal itu mengacaukan ruang nama importir, dan mempersulit linter untuk mendeteksi nama yang tidak ditentukan Impor modul di bagian atas file. Melakukan hal itu memperjelas modul apa yang dibutuhkan kode Anda dan menghindari pertanyaan apakah nama modul ada dalam cakupan. Menggunakan satu impor per baris memudahkan untuk menambah dan menghapus impor modul, tetapi menggunakan banyak impor per baris menggunakan lebih sedikit ruang layar Ini praktik yang baik jika Anda mengimpor modul dalam urutan berikut
Terkadang perlu memindahkan impor ke fungsi atau kelas untuk menghindari masalah dengan impor melingkar. kata Gordon McMillan
Dalam hal ini, jika modul kedua hanya digunakan dalam satu fungsi, maka impor dapat dengan mudah dipindahkan ke fungsi tersebut. Pada saat impor dipanggil, modul pertama sudah selesai diinisialisasi, dan modul kedua dapat melakukan impornya Mungkin juga diperlukan untuk memindahkan impor dari kode tingkat atas jika beberapa modul khusus untuk platform. Dalam hal ini, bahkan tidak mungkin untuk mengimpor semua modul di bagian atas file. Dalam hal ini, mengimpor modul yang benar dalam kode khusus platform yang sesuai adalah pilihan yang baik Hanya pindahkan impor ke lingkup lokal, seperti di dalam definisi fungsi, jika diperlukan untuk menyelesaikan masalah seperti menghindari impor melingkar atau mencoba mengurangi waktu inisialisasi modul. Teknik ini sangat membantu jika banyak impor yang tidak diperlukan bergantung pada bagaimana program dijalankan. Anda mungkin juga ingin memindahkan impor ke suatu fungsi jika modul hanya digunakan dalam fungsi itu. Perhatikan bahwa memuat modul pertama kali mungkin mahal karena inisialisasi modul satu kali, tetapi memuat modul berkali-kali sebenarnya gratis, hanya menghabiskan beberapa pencarian kamus. Bahkan jika nama modul telah keluar dari ruang lingkup, modul tersebut mungkin tersedia di Jenis bug ini biasanya menggigit programmer pemula. Pertimbangkan fungsi ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_4 Pertama kali Anda memanggil fungsi ini, >>> x = 10 >>> def foo(): .. print(x) .. x += 1_61 berisi satu item. Kedua kalinya, >>> x = 10 >>> def foo(): .. print(x) .. x += 1_61 berisi dua item karena ketika >>> x = 10 >>> def foo(): .. print(x) .. x += 163 mulai dijalankan, >>> x = 10 >>> def foo(): .. print(x) .. x += 161 dimulai dengan item yang sudah ada di dalamnya Seringkali pemanggilan fungsi diharapkan membuat objek baru untuk nilai default. Bukan ini yang terjadi. Nilai default dibuat tepat satu kali, saat fungsi ditentukan. Jika objek itu diubah, seperti kamus dalam contoh ini, panggilan selanjutnya ke fungsi tersebut akan merujuk ke objek yang diubah ini Menurut definisi, objek yang tidak dapat diubah seperti angka, string, tupel, dan >>> x = 10 >>> def foo(): .. print(x) .. x += 165, aman dari perubahan. Perubahan pada objek yang dapat diubah seperti kamus, daftar, dan instance kelas dapat menyebabkan kebingungan Karena fitur ini, merupakan praktik pemrograman yang baik untuk tidak menggunakan objek yang dapat diubah sebagai nilai default. Alih-alih, gunakan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_65 sebagai nilai default dan di dalam fungsi, periksa apakah parameternya adalah >>> x = 10 >>> def foo(): .. print(x) .. x += 165 dan buat daftar/kamus baru/apa pun jika itu. Misalnya, jangan menulis >>> x = 10 >>> def foo(): .. print(x) .. x += 1_5 tetapi >>> x = 10 >>> def foo(): .. print(x) .. x += 1_6 Fitur ini dapat bermanfaat. Saat Anda memiliki fungsi yang memakan waktu komputasi, teknik yang umum adalah meng-cache parameter dan nilai yang dihasilkan dari setiap panggilan ke fungsi, dan mengembalikan nilai yang di-cache jika nilai yang sama diminta lagi. Ini disebut "memoisasi", dan dapat diimplementasikan seperti ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_7 Anda bisa menggunakan variabel global yang berisi kamus alih-alih nilai default; Kumpulkan argumen menggunakan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_68 dan >>> x = 10 >>> def foo(): .. print(x) .. x += 169 penentu dalam daftar parameter fungsi; . Anda kemudian dapat meneruskan argumen ini saat memanggil fungsi lain dengan menggunakan >>> x = 10 >>> def foo(): .. print(x) .. x += 168 dan >>> x = 10 >>> def foo(): .. print(x) .. x += 169 >>> x = 10 >>> def foo(): .. print(x) .. x += 1_8 didefinisikan oleh nama yang muncul dalam definisi fungsi, sedangkan nilai sebenarnya diteruskan ke fungsi saat memanggilnya. Parameter menentukan apa yang dapat diterima oleh suatu fungsi. Misalnya, diberikan definisi fungsi >>> x = 10 >>> def foo(): .. print(x) .. x += 1_9 foo, bar dan kwargs adalah parameter dari >>> x = 10 >>> def foo(): .. print(x) .. x += 172. Namun, saat menelepon >>> x = 10 >>> def foo(): .. print(x) .. x += 1_72, misalnya >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment0 nilai >>> x = 10 >>> def foo(): .. print(x) .. x += 1_74, >>> x = 10 >>> def foo(): .. print(x) .. x += 175, dan >>> x = 10 >>> def foo(): .. print(x) .. x += 176 adalah argumen Jika Anda menulis kode seperti >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment1 Anda mungkin bertanya-tanya mengapa menambahkan elemen ke >>> x = 10 >>> def foo(): .. print(x) .. x += 177 mengubah >>> x = 10 >>> def foo(): .. print(x) .. x += 124 juga Ada dua faktor yang menghasilkan hasil ini
Setelah panggilan ke >>> x = 10 >>> def foo(): .. print(x) .. x += 1_84, konten objek yang dapat diubah telah berubah dari >>> x = 10 >>> def foo(): .. print(x) .. x += 185 menjadi >>> x = 10 >>> def foo(): .. print(x) .. x += 186. Karena kedua variabel merujuk ke objek yang sama, menggunakan salah satu nama mengakses nilai yang dimodifikasi >>> x = 10 >>> def foo(): .. print(x) .. x += 186 Jika kami malah menetapkan objek yang tidak dapat diubah ke >>> x = 10 >>> def foo(): .. print(x) .. x += 124 >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment2 kita dapat melihat bahwa dalam hal ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_24 dan >>> x = 10 >>> def foo(): .. print(x) .. x += 177 tidak sama lagi. Ini karena bilangan bulat adalah , dan ketika kita melakukannya >>> x = 10 >>> def foo(): .. print(x) .. x += 191 kita tidak mengubah int >>> x = 10 >>> def foo(): .. print(x) .. x += 192 dengan menaikkan nilainya; . Setelah penugasan ini, kami memiliki dua objek (int >>> x = 10 >>> def foo(): .. print(x) .. x += 193 dan >>> x = 10 >>> def foo(): .. print(x) .. x += 192) dan dua variabel yang merujuk ke mereka ( >>> x = 10 >>> def foo(): .. print(x) .. x += 124 sekarang merujuk ke >>> x = 10 >>> def foo(): .. print(x) .. x += 193 tetapi >>> x = 10 >>> def foo(): .. print(x) .. x += 177 masih merujuk ke >>> x = 10 >>> def foo(): .. print(x) .. x += 192) Beberapa operasi (misalnya >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment02 dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment03) mengubah objek, sedangkan operasi yang mirip secara dangkal (misalnya >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment04 dan ) membuat objek baru. Secara umum dalam Python (dan dalam semua kasus di perpustakaan standar) metode yang memutasi objek akan mengembalikan >>> x = 10 >>> def foo(): .. print(x) .. x += 165 untuk membantu menghindari dua jenis operasi yang membingungkan. Jadi, jika Anda keliru menulis >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_03 berpikir itu akan memberi Anda salinan >>> x = 10 >>> def foo(): .. print(x) .. x += 177 yang telah diurutkan, Anda malah akan berakhir dengan >>> x = 10 >>> def foo(): .. print(x) .. x += 165, yang kemungkinan akan menyebabkan program Anda menghasilkan kesalahan yang mudah didiagnosis Namun, ada satu kelas operasi dimana operasi yang sama terkadang memiliki perilaku yang berbeda dengan tipe yang berbeda. operator penugasan ditambah. Misalnya, >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10 memutasikan daftar tetapi bukan tupel atau int ( >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment11 setara dengan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment12 dan memutasikan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment13, sedangkan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment14 dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment15 membuat objek baru) Dengan kata lain
Jika Anda ingin mengetahui apakah dua variabel merujuk ke objek yang sama atau tidak, Anda dapat menggunakan operator, atau fungsi bawaan Ingatlah bahwa argumen diteruskan dengan penugasan di Python. Karena penugasan hanya membuat referensi ke objek, tidak ada alias antara nama argumen di pemanggil dan yang dipanggil, jadi tidak ada referensi panggilan per se. Anda dapat mencapai efek yang diinginkan dengan beberapa cara
Pilihan terbaik Anda adalah mengembalikan tuple yang berisi banyak hasil Anda memiliki dua pilihan. Anda dapat menggunakan cakupan bersarang atau Anda dapat menggunakan objek yang dapat dipanggil. Misalnya, Anda ingin mendefinisikan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_24 yang mengembalikan fungsi >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment25 yang menghitung nilai >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment26. Menggunakan lingkup bersarang >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_7 Atau menggunakan objek yang bisa dipanggil >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment8 Dalam kedua kasus tersebut, >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_9 memberikan objek yang dapat dipanggil di mana >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_27 Pendekatan objek yang dapat dipanggil memiliki kelemahan yaitu sedikit lebih lambat dan menghasilkan kode yang sedikit lebih panjang. Namun, perhatikan bahwa kumpulan callable dapat membagikan tanda tangan mereka melalui pewarisan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_0 Objek dapat mengenkapsulasi status untuk beberapa metode >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_1 Di sini >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_28, >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment29 dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment30 bertindak seperti fungsi yang berbagi variabel penghitungan yang sama Secara umum, coba atau untuk kasus umum. Tidak semua objek bisa disalin, tapi sebagian besar bisa Beberapa objek dapat disalin dengan lebih mudah. Kamus memiliki metode >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_2 Urutan dapat disalin dengan mengiris >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_3 Untuk instance >>> x = 10 >>> def foo(): .. print(x) .. x += 124 dari kelas yang ditentukan pengguna, mengembalikan daftar alfabet dari nama yang berisi atribut dan metode instan dan atribut yang ditentukan oleh kelasnya Secara umum, tidak bisa, karena objek sebenarnya tidak memiliki nama. Pada dasarnya, penugasan selalu mengikat sebuah nama ke sebuah nilai; . Pertimbangkan kode berikut >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_4 Bisa dibilang kelas tersebut memiliki nama. meskipun terikat pada dua nama dan dipanggil melalui nama >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment38 instance yang dibuat masih dilaporkan sebagai instance dari kelas >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment39. Namun, tidak mungkin untuk mengatakan apakah nama instance adalah >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment40 atau >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment41, karena kedua nama terikat dengan nilai yang sama Secara umum, kode Anda tidak perlu "mengetahui nama" dari nilai tertentu. Kecuali jika Anda sengaja menulis program introspektif, ini biasanya merupakan indikasi bahwa perubahan pendekatan mungkin bermanfaat Dalam komp. lang. python, Fredrik Lundh pernah memberikan analogi yang sangat bagus untuk menjawab pertanyaan ini
Koma bukan operator di Python. Pertimbangkan sesi ini >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_5 Karena koma bukan operator, tetapi pemisah antara ekspresi di atas dievaluasi seolah-olah Anda telah memasukkannya >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_6 bukan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_7 Hal yang sama berlaku untuk berbagai operator penugasan ( >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment42, >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10 dll). Mereka sebenarnya bukan operator tetapi pembatas sintaksis dalam pernyataan penugasan Ya ada. Sintaksnya adalah sebagai berikut >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_8 Sebelum sintaks ini diperkenalkan di Python 2. 5, idiom umum adalah menggunakan operator logika >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_9 Namun, idiom ini tidak aman, karena dapat memberikan hasil yang salah ketika on_true memiliki nilai boolean yang salah. Oleh karena itu, selalu lebih baik menggunakan formulir ________3______44 Ya. Biasanya ini dilakukan dengan bersarang di dalam >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_45. Lihat tiga contoh berikut, sedikit diadaptasi dari Ulf Bartelt >>> print(x) 110 Jangan coba ini di rumah, anak-anak Garis miring dalam daftar argumen suatu fungsi menunjukkan bahwa parameter sebelumnya hanya untuk posisi. Parameter khusus posisi adalah parameter tanpa nama yang dapat digunakan secara eksternal. Saat memanggil fungsi yang menerima parameter hanya posisional, argumen dipetakan ke parameter hanya berdasarkan posisinya. Misalnya, adalah fungsi yang menerima parameter hanya posisi. Dokumentasinya terlihat seperti ini >>> print(x) 111 Garis miring di akhir daftar parameter berarti kedua parameter hanya untuk posisi. Jadi, memanggil dengan argumen kata kunci akan menyebabkan kesalahan >>> print(x) 112 Untuk menentukan digit oktal, awali nilai oktal dengan nol, lalu huruf kecil atau huruf besar “o”. Misalnya, untuk mengatur variabel "a" ke nilai oktal "10" (8 dalam desimal), ketik >>> print(x) 113 Heksadesimal sama mudahnya. Cukup awali angka heksadesimal dengan nol, lalu huruf kecil atau besar “x”. Digit heksadesimal dapat ditentukan dalam huruf kecil atau huruf besar. Misalnya, dalam juru bahasa Python >>> print(x) 114 Ini terutama didorong oleh keinginan bahwa >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment49 memiliki tanda yang sama dengan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment50. Jika Anda menginginkannya, dan juga menginginkannya >>> print(x) 115 maka pembagian bilangan bulat harus mengembalikan lantai. C juga mengharuskan identitas tersebut dipertahankan, dan kemudian kompiler yang memotong >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment51 perlu membuat >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment49 memiliki tanda yang sama dengan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment53 Ada beberapa kasus penggunaan nyata untuk >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_49 saat >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment50 negatif. Ketika >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_50 positif, ada banyak, dan hampir semuanya lebih berguna untuk >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment49 menjadi >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment58. Jika jam mengatakan 10 sekarang, apa yang dikatakan 200 jam yang lalu? Mencoba mencari >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_20 atribut literal dengan cara normal memberikan a karena periode dipandang sebagai titik desimal >>> print(x) 116 Solusinya adalah memisahkan literal dari titik dengan spasi atau tanda kurung >>> print(x) 117 Untuk bilangan bulat, gunakan konstruktor tipe bawaan, mis. g. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_64. Demikian pula, mengkonversi ke floating-point, mis. g. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_66 Secara default, ini mengartikan angka sebagai desimal, sehingga >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment67 benar, dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment68 memunculkan. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment70 mengambil basis untuk dikonversi dari sebagai argumen opsional kedua, jadi >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment71. Jika basis ditentukan sebagai 0, angka tersebut ditafsirkan menggunakan aturan Python. awalan '0o' menunjukkan oktal, dan '0x' menunjukkan angka hex Jangan gunakan fungsi bawaan jika yang Anda butuhkan hanyalah mengonversi string menjadi angka. akan secara signifikan lebih lambat dan menimbulkan risiko keamanan. seseorang dapat memberi Anda ekspresi Python yang mungkin memiliki efek samping yang tidak diinginkan. Misalnya, seseorang dapat mengirimkan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment74 yang akan menghapus direktori home Anda juga memiliki efek menafsirkan angka sebagai ekspresi Python, sehingga e. g. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment76 memberikan kesalahan sintaksis karena Python tidak mengizinkan awalan '0' dalam angka desimal (kecuali '0') Untuk mengkonversi, e. g. , nomor >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment77 ke string >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment78, gunakan konstruktor tipe bawaan. Jika Anda menginginkan representasi heksadesimal atau oktal, gunakan fungsi bawaan atau. Untuk pemformatan mewah, lihat bagian dan, mis. g. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment82 menghasilkan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment83 dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment84 menghasilkan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment85 Anda tidak bisa, karena string tidak dapat diubah. Dalam kebanyakan situasi, Anda cukup membuat string baru dari berbagai bagian yang ingin Anda rakit. Namun, jika Anda memerlukan objek dengan kemampuan untuk mengubah data unicode di tempat, coba gunakan objek atau modul >>> print(x) 11_8 Ada berbagai teknik
Anda dapat menggunakan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_91 untuk menghapus semua kemunculan terminator baris apa pun dari akhir string >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment92 tanpa menghapus spasi kosong lainnya. Jika string >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment92 mewakili lebih dari satu baris, dengan beberapa baris kosong di akhir, baris terminator untuk semua baris kosong akan dihapus >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_3 Karena ini biasanya hanya diinginkan saat membaca teks satu baris pada satu waktu, menggunakan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment94 cara ini bekerja dengan baik Tidak seperti itu Untuk penguraian input sederhana, pendekatan termudah biasanya adalah membagi baris menjadi kata-kata yang dipisahkan spasi menggunakan metode objek string dan kemudian mengonversi string desimal menjadi nilai numerik menggunakan atau. >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment95 mendukung parameter "sep" opsional yang berguna jika garis menggunakan sesuatu selain spasi putih sebagai pemisah Untuk penguraian input yang lebih rumit, ekspresi reguler lebih kuat daripada C >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment99 dan lebih cocok untuk tugas tersebut Lihat String mentah yang diakhiri dengan garis miring terbalik dalam jumlah ganjil akan lolos dari kutipan string >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_4 Ada beberapa solusi untuk ini. Salah satunya adalah menggunakan string biasa dan menggandakan garis miring terbalik >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_5 Cara lainnya adalah menggabungkan string biasa yang berisi tanda garis miring terbalik ke string mentah >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_6 Dimungkinkan juga untuk menggunakan garis miring terbalik pada Windows >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_7 Perhatikan bahwa meskipun garis miring terbalik akan "melarikan diri" dari kutipan untuk tujuan menentukan di mana string mentah berakhir, tidak ada pelolosan yang terjadi saat menginterpretasikan nilai string mentah. Artinya, garis miring terbalik tetap ada pada nilai string mentah >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_8 Lihat juga spesifikasinya di Itu yang sulit, secara umum. Pertama, berikut adalah daftar hal yang perlu diingat sebelum menyelam lebih jauh
Meski begitu, ada banyak trik untuk mempercepat kode Python. Berikut adalah beberapa prinsip umum yang sangat membantu untuk mencapai tingkat kinerja yang dapat diterima
Jika Anda telah mencapai batas yang diperbolehkan oleh Python murni, ada alat untuk membawa Anda lebih jauh. Misalnya, Cython dapat mengkompilasi versi kode Python yang sedikit dimodifikasi menjadi ekstensi C, dan dapat digunakan di banyak platform berbeda. Cython dapat memanfaatkan kompilasi (dan anotasi tipe opsional) untuk membuat kode Anda jauh lebih cepat daripada saat ditafsirkan. Jika Anda yakin dengan keterampilan pemrograman C Anda, Anda juga bisa melakukannya sendiri Lihat juga Halaman wiki yang dikhususkan untuk tip kinerja dan objek tidak dapat diubah, oleh karena itu menggabungkan banyak string menjadi tidak efisien karena setiap penggabungan membuat objek baru. Dalam kasus umum, total biaya runtime adalah kuadrat dalam total panjang string Untuk mengumpulkan banyak objek, idiom yang disarankan adalah menempatkannya ke dalam daftar dan menelepon di bagian akhir >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_9 (idiom lain yang cukup efisien adalah menggunakan ) Untuk mengumpulkan banyak objek, idiom yang disarankan adalah memperluas objek menggunakan penggabungan di tempat (operator >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10) >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)0 Konstruktor tipe >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1014 mengubah urutan apa pun (sebenarnya, iterable apa pun) menjadi tuple dengan item yang sama dalam urutan yang sama Misalnya, >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_15 menghasilkan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1016 dan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1017 menghasilkan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1018. Jika argumennya adalah tuple, itu tidak membuat salinan tetapi mengembalikan objek yang sama, jadi murah untuk menelepon ketika Anda tidak yakin bahwa suatu objek sudah menjadi tuple Konstruktor tipe >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1020 mengubah urutan apa pun atau iterable menjadi daftar dengan item yang sama dalam urutan yang sama. Misalnya, >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_21 menghasilkan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1022 dan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1023 menghasilkan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1024. Jika argumennya adalah daftar, itu membuat salinan seperti >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1025 Urutan python diindeks dengan angka positif dan angka negatif. Untuk bilangan positif 0 adalah indeks pertama 1 adalah indeks kedua dan seterusnya. Untuk indeks negatif -1 adalah indeks terakhir dan -2 adalah indeks kedua dari belakang (di sebelah terakhir) dan seterusnya. Pikirkan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_26 sama dengan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1027 Menggunakan indeks negatif bisa sangat nyaman. Misalnya >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_28 adalah semua string kecuali karakter terakhirnya, yang berguna untuk menghapus baris baru dari sebuah string Gunakan fungsi bawaan >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)1 Ini tidak akan menyentuh urutan asli Anda, tetapi buat salinan baru dengan urutan terbalik untuk mengulanginya Lihat Buku Masak Python untuk diskusi panjang tentang banyak cara untuk melakukan ini
Jika Anda tidak keberatan menyusun ulang daftar, urutkan, lalu pindai dari akhir daftar, hapus duplikat saat Anda melakukannya >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)2 Jika semua elemen daftar dapat digunakan sebagai kunci set (mis. e. mereka semua ) ini seringkali lebih cepat >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)3 Ini mengubah daftar menjadi satu set, sehingga menghapus duplikat, dan kemudian kembali ke daftar Seperti halnya menghapus duplikat, iterasi secara terbalik secara eksplisit dengan kondisi hapus adalah salah satu kemungkinannya. Namun, lebih mudah dan lebih cepat untuk menggunakan penggantian irisan dengan iterasi maju implisit atau eksplisit. Berikut adalah tiga variasi >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)4 Pemahaman daftar mungkin tercepat Gunakan daftar >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)5 Daftar setara dengan array C atau Pascal dalam kompleksitas waktunya; Modul >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_87 juga menyediakan metode untuk membuat array tipe tetap dengan representasi kompak, tetapi lebih lambat untuk mengindeks daripada daftar. Perhatikan juga bahwa NumPy dan paket pihak ketiga lainnya juga mendefinisikan struktur seperti array dengan berbagai karakteristik Untuk mendapatkan daftar tertaut gaya Lisp, Anda dapat meniru sel kontra menggunakan tupel >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)6 Jika mutabilitas diinginkan, Anda bisa menggunakan daftar, bukan tupel. Di sini analog mobil Lisp adalah >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1031 dan analog cdr adalah >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1032. Lakukan ini hanya jika Anda yakin benar-benar perlu, karena biasanya jauh lebih lambat daripada menggunakan daftar Python Anda mungkin mencoba membuat array multidimensi seperti ini >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)7 Ini terlihat benar jika Anda mencetaknya >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)8 Namun saat Anda menetapkan nilai, nilai itu muncul di banyak tempat >>> squares = [] >>> for x in range(5): .. squares.append(lambda: x**2)_9 Alasannya adalah mereplikasi daftar dengan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_68 tidak membuat salinan, itu hanya membuat referensi ke objek yang ada. The >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1034 membuat daftar yang berisi 3 referensi ke daftar yang sama dengan panjang dua. Perubahan pada satu baris akan ditampilkan di semua baris, yang hampir pasti bukan yang Anda inginkan Pendekatan yang disarankan adalah membuat daftar dengan panjang yang diinginkan terlebih dahulu lalu mengisi setiap elemen dengan daftar yang baru dibuat >>> squares[2]() 16 >>> squares[4]() 160 Ini menghasilkan daftar yang berisi 3 daftar berbeda dengan panjang dua. Anda juga dapat menggunakan pemahaman daftar >>> squares[2]() 16 >>> squares[4]() 161 Atau, Anda dapat menggunakan ekstensi yang menyediakan tipe data matriks; Untuk memanggil metode atau fungsi dan mengumpulkan nilai pengembalian adalah daftar, a adalah solusi yang elegan >>> squares[2]() 16 >>> squares[4]() 162 Untuk hanya menjalankan metode atau fungsi tanpa menyimpan nilai yang dikembalikan, loop biasa sudah cukup >>> squares[2]() 16 >>> squares[4]() 163 Ini karena kombinasi dari fakta bahwa operator penugasan yang diperbesar adalah operator penugasan, dan perbedaan antara objek yang dapat diubah dan yang tidak dapat diubah di Python Diskusi ini berlaku secara umum ketika operator penugasan tambahan diterapkan ke elemen tupel yang mengarah ke objek yang dapat diubah, tetapi kami akan menggunakan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment16 dan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10 sebagai contoh kami Jika Anda menulis >>> squares[2]() 16 >>> squares[4]() 164 Alasan pengecualian harus segera jelas. >>> x = 10 >>> def foo(): .. print(x) .. x += 1_33 ditambahkan ke objek >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1039 menunjuk ke ( >>> x = 10 >>> def foo(): .. print(x) .. x += 133), menghasilkan objek hasil, >>> x = 10 >>> def foo(): .. print(x) .. x += 151, tetapi ketika kami mencoba untuk menetapkan hasil perhitungan, >>> x = 10 >>> def foo(): .. print(x) .. x += 151, ke elemen >>> x = 10 >>> def foo(): .. print(x) .. x += 132 dari tuple, kami mendapatkan kesalahan karena kami tidak bisa Di balik selimut, apa yang dilakukan pernyataan penugasan tambahan ini kira-kira seperti ini >>> squares[2]() 16 >>> squares[4]() 165 Itu adalah bagian penugasan dari operasi yang menghasilkan kesalahan, karena tupel tidak dapat diubah Ketika Anda menulis sesuatu seperti >>> squares[2]() 16 >>> squares[4]() 166 Pengecualian ini sedikit lebih mengejutkan, dan yang lebih mengejutkan lagi adalah fakta bahwa meskipun ada kesalahan, appendnya berfungsi >>> squares[2]() 16 >>> squares[4]() 167 Untuk mengetahui mengapa hal ini terjadi, Anda perlu mengetahui bahwa (a) jika sebuah objek mengimplementasikan metode ajaib, objek tersebut akan dipanggil saat penugasan tambahan >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10 dijalankan, dan nilai pengembaliannya digunakan dalam pernyataan penugasan; . Itu sebabnya kami mengatakan bahwa untuk daftar, >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment10 adalah "singkatan" untuk >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1049 >>> squares[2]() 16 >>> squares[4]() 168 Ini setara dengan >>> squares[2]() 16 >>> squares[4]() 16_9 Objek yang ditunjuk oleh a_list telah dimutasi, dan penunjuk ke objek yang dimutasi ditugaskan kembali ke >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment13. Hasil akhir dari penugasan adalah no-op, karena ini adalah penunjuk ke objek yang sama yang sebelumnya ditunjuk oleh >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment13, tetapi penugasan tetap terjadi Jadi, dalam contoh tuple kita apa yang terjadi setara dengan >>> x = 8 >>> squares[2]() 64_0 >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1044 berhasil, dan dengan demikian daftar diperpanjang, tetapi meskipun >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1053 menunjuk ke objek yang sama yang >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1039 sudah menunjuk ke, tugas akhir itu masih menghasilkan kesalahan, karena tupel tidak dapat diubah Teknik tersebut, dikaitkan dengan Randal Schwartz dari komunitas Perl, mengurutkan elemen daftar dengan metrik yang memetakan setiap elemen ke "nilai pengurutan" -nya. Di Python, gunakan argumen >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_55 untuk metode ini >>> x = 8 >>> squares[2]() 64_1 Gabungkan mereka menjadi iterator tupel, urutkan daftar yang dihasilkan, lalu pilih elemen yang Anda inginkan >>> x = 8 >>> squares[2]() 64_2 Kelas adalah tipe objek tertentu yang dibuat dengan mengeksekusi pernyataan kelas. Objek kelas digunakan sebagai templat untuk membuat objek instan, yang mewujudkan data (atribut) dan kode (metode) khusus untuk tipe data Kelas dapat didasarkan pada satu atau lebih kelas lain, yang disebut kelas dasarnya (es). Itu kemudian mewarisi atribut dan metode kelas dasarnya. Ini memungkinkan model objek untuk disempurnakan secara berturut-turut dengan pewarisan. Anda mungkin memiliki kelas >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1057 generik yang menyediakan metode pengakses dasar untuk kotak surat, dan subkelas seperti >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1058, >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1059, >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1060 yang menangani berbagai format kotak surat tertentu Metode adalah fungsi pada beberapa objek >>> x = 10 >>> def foo(): .. print(x) .. x += 1_24 yang biasanya Anda panggil sebagai >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1062. Metode didefinisikan sebagai fungsi di dalam definisi kelas >>> x = 8 >>> squares[2]() 64_3 Diri hanyalah sebuah nama konvensional untuk argumen pertama dari sebuah metode. Sebuah metode didefinisikan sebagai >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1063 harus disebut sebagai >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1064 untuk beberapa contoh >>> x = 10 >>> def foo(): .. print(x) .. x += 124 dari kelas di mana definisi terjadi; Lihat juga Gunakan fungsi bawaan. Anda dapat memeriksa apakah suatu objek adalah turunan dari sejumlah kelas dengan menyediakan tuple alih-alih satu kelas, mis. g. >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_68, dan juga dapat memeriksa apakah suatu objek adalah salah satu tipe bawaan Python, e. g. >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_69 atau >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1070 Perhatikan bahwa juga memeriksa warisan virtual dari sebuah. Jadi, tes akan mengembalikan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_72 untuk kelas terdaftar meskipun tidak diwarisi secara langsung atau tidak langsung darinya. Untuk menguji "warisan sebenarnya", pindai kelas >>> x = 8 >>> squares[2]() 64_4 >>> x = 8 >>> squares[2]() 64_5 Perhatikan bahwa sebagian besar program tidak terlalu sering digunakan pada kelas yang ditentukan pengguna. Jika Anda mengembangkan kelas sendiri, gaya berorientasi objek yang lebih tepat adalah mendefinisikan metode pada kelas yang merangkum perilaku tertentu, alih-alih memeriksa kelas objek dan melakukan hal yang berbeda berdasarkan kelas apa itu. Misalnya, jika Anda memiliki fungsi yang melakukan sesuatu >>> x = 8 >>> squares[2]() 64_6 Pendekatan yang lebih baik adalah dengan mendefinisikan metode >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_74 di semua kelas dan sebut saja >>> x = 8 >>> squares[2]() 64_7 Delegasi adalah teknik berorientasi objek (juga disebut pola desain). Katakanlah Anda memiliki objek >>> x = 10 >>> def foo(): .. print(x) .. x += 1_24 dan ingin mengubah perilaku salah satu metode saja. Anda dapat membuat kelas baru yang menyediakan implementasi baru dari metode yang ingin Anda ubah dan mendelegasikan semua metode lain ke metode yang sesuai dari >>> x = 10 >>> def foo(): .. print(x) .. x += 124 Pemrogram Python dapat dengan mudah mengimplementasikan delegasi. Misalnya, kelas berikut mengimplementasikan kelas yang berperilaku seperti file tetapi mengubah semua data tertulis menjadi huruf besar >>> x = 8 >>> squares[2]() 64_8 Di sini kelas >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_77 mengubah metode >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1078 untuk mengonversi string argumen menjadi huruf besar sebelum memanggil metode >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1079 yang mendasarinya. Semua metode lain didelegasikan ke objek >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1080 yang mendasarinya. Pendelegasian dilakukan melalui metode; Perhatikan bahwa untuk kasus yang lebih umum, pendelegasian bisa menjadi lebih rumit. Ketika atribut harus disetel dan juga diambil, kelas juga harus menentukan metode, dan harus melakukannya dengan hati-hati. Implementasi dasar >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_82 kira-kira setara dengan yang berikut ini >>> x = 8 >>> squares[2]() 64_9 Sebagian besar implementasi >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_82 harus dimodifikasi untuk menyimpan status lokal untuk dirinya sendiri tanpa menyebabkan rekursi tak terbatas Gunakan fungsi bawaan >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)0 Dalam contoh, akan secara otomatis menentukan instance dari mana ia dipanggil (nilai >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1088), mencari (MRO) dengan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1089, dan mengembalikan baris berikutnya setelah >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1090 di MRO. >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_91 Anda bisa menetapkan kelas dasar ke alias dan berasal dari alias. Maka yang harus Anda ubah hanyalah nilai yang diberikan ke alias. Kebetulan, trik ini juga berguna jika Anda ingin memutuskan secara dinamis (mis. g. tergantung pada ketersediaan sumber daya) kelas dasar mana yang akan digunakan. Contoh >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)1 Baik data statis maupun metode statis (dalam pengertian C++ atau Java) didukung dengan Python Untuk data statis, cukup tentukan atribut kelas. Untuk menetapkan nilai baru ke atribut, Anda harus menggunakan nama kelas secara eksplisit dalam penetapan >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)2 >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_92 juga mengacu pada >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1093 untuk >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1094 seperti yang >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1095 berlaku, kecuali diganti oleh >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1094 itu sendiri atau oleh beberapa kelas di jalur pencarian kelas dasar dari >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1097 kembali ke >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1098 Hati-hati. dalam metode C, penugasan seperti >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 10_99 membuat instance baru dan tidak terkait bernama "menghitung" di dict >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1088 sendiri. Pengikatan ulang nama data statis kelas harus selalu menentukan kelas apakah di dalam metode atau tidak >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)3 Metode statis dimungkinkan >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)4 Namun, cara yang jauh lebih mudah untuk mendapatkan efek dari metode statis adalah melalui fungsi tingkat modul yang sederhana >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)5 Jika kode Anda terstruktur untuk mendefinisikan satu kelas (atau hierarki kelas yang terkait erat) per modul, ini menyediakan enkapsulasi yang diinginkan Jawaban ini sebenarnya berlaku untuk semua metode, tetapi pertanyaan biasanya muncul pertama kali dalam konteks konstruktor Di C++ Anda akan menulis >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)6 Di Python Anda harus menulis satu konstruktor yang menangkap semua kasus menggunakan argumen default. Sebagai contoh >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)7 Ini tidak sepenuhnya setara, tetapi cukup dekat dalam praktiknya Anda juga bisa mencoba daftar argumen dengan panjang variabel, mis. g >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)8 Pendekatan yang sama berlaku untuk semua definisi metode Nama variabel dengan garis bawah ganda di depan "hancur" untuk menyediakan cara sederhana namun efektif untuk mendefinisikan variabel privat kelas. Pengidentifikasi apa pun dalam bentuk >>> print(x) 1101 (setidaknya dua garis bawah di depan, paling banyak satu garis bawah di belakang) secara tekstual diganti dengan >>> print(x) 1102, di mana >>> print(x) 1103 adalah nama kelas saat ini dengan garis bawah di depan yang dihilangkan Ini tidak menjamin privasi. pengguna luar masih dapat dengan sengaja mengakses atribut "_classname__spam", dan nilai pribadi terlihat di >>> print(x) 1104 objek. Banyak programmer Python tidak pernah repot-repot menggunakan nama variabel pribadi sama sekali Ada beberapa kemungkinan alasan untuk ini Pernyataan itu tidak harus memanggil - itu hanya mengurangi jumlah referensi objek, dan jika ini mencapai nol >>> print(x) 1106 disebut Jika struktur data Anda berisi tautan melingkar (mis. g. pohon di mana setiap anak memiliki referensi orang tua dan setiap orang tua memiliki daftar anak-anak) jumlah referensi tidak akan pernah kembali ke nol. Sesekali Python menjalankan algoritme untuk mendeteksi siklus seperti itu, tetapi pengumpul sampah mungkin berjalan beberapa saat setelah referensi terakhir ke struktur data Anda hilang, sehingga metode >>> print(x) 1106 Anda dapat dipanggil pada waktu yang tidak nyaman dan acak. Ini merepotkan jika Anda mencoba mereproduksi masalah. Lebih buruk lagi, urutan eksekusi metode ________7______06 objek bersifat arbitrer. Anda dapat menjalankan untuk memaksa pengumpulan, tetapi ada kasus patologis di mana objek tidak akan pernah dikumpulkan Terlepas dari pengumpul siklus, masih merupakan ide bagus untuk mendefinisikan metode >>> print(x) 1111 eksplisit pada objek yang akan dipanggil setiap kali Anda selesai menggunakannya. Metode >>> print(x) 11_11 kemudian dapat menghapus atribut yang merujuk ke subobjek. Jangan panggil >>> print(x) 11_06 secara langsung – >>> print(x) 1106 harus menelepon >>> print(x) 1111 dan >>> print(x) 1111 harus memastikan bahwa itu dapat dipanggil lebih dari sekali untuk objek yang sama Cara lain untuk menghindari referensi siklis adalah dengan menggunakan modul, yang memungkinkan Anda menunjuk ke objek tanpa menambah jumlah referensinya. Struktur data pohon, misalnya, harus menggunakan referensi yang lemah untuk referensi orang tua dan saudara kandungnya (jika mereka membutuhkannya. ) Terakhir, jika metode >>> print(x) 11_06 Anda memunculkan pengecualian, pesan peringatan akan dicetak ke Python tidak melacak semua contoh kelas (atau tipe bawaan). Anda dapat memprogram konstruktor kelas untuk melacak semua instance dengan menyimpan daftar referensi yang lemah untuk setiap instance Builtin mengembalikan bilangan bulat yang dijamin unik selama masa pakai objek. Karena di CPython, ini adalah alamat memori objek, sering terjadi setelah objek dihapus dari memori, objek yang baru dibuat berikutnya dialokasikan pada posisi yang sama di memori. Ini diilustrasikan oleh contoh ini >>> squares = [] >>> for x in range(5): .. squares.append(lambda n=x: n**2)_9 Kedua id milik objek bilangan bulat berbeda yang dibuat sebelumnya, dan dihapus segera setelah eksekusi panggilan >>> x = 10 >>> def foo(): .. print(x) .. x += 119. Untuk memastikan objek yang id-nya ingin Anda periksa masih hidup, buat referensi lain ke objek tersebut >>> x = 10 >>> def foo(): .. print(x) .. x += 1_00 Operator >>> foo() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment_22 menguji identitas objek. Tes >>> print(x) 11_24 setara dengan >>> print(x) 1125 Properti paling penting dari tes identitas adalah bahwa objek selalu identik dengan dirinya sendiri, >>> print(x) 1126 selalu mengembalikan >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1072. Tes identitas biasanya lebih cepat daripada tes kesetaraan. Dan tidak seperti tes kesetaraan, tes identitas dijamin untuk mengembalikan boolean >>> x = 10 >>> def foobar(): .. global x .. print(x) .. x += 1 ... >>> foobar() 1072 atau >>> print(x) 1129 Namun, tes identitas hanya dapat diganti dengan tes kesetaraan ketika identitas objek terjamin. Secara umum, ada tiga keadaan di mana identitas dijamin 1) Tugas membuat nama baru tetapi tidak mengubah identitas objek. Setelah penugasan >>> print(x) 11_30, dijamin bahwa >>> print(x) 1131 2) Memasukkan objek ke dalam wadah yang menyimpan referensi objek tidak mengubah identitas objek. Setelah penugasan daftar >>> print(x) 11_32, dijamin bahwa >>> print(x) 1133 3) Jika suatu objek adalah singleton, itu berarti hanya ada satu instance dari objek itu. Setelah penugasan >>> print(x) 1134 dan >>> print(x) 1135, dijamin bahwa >>> print(x) 1124 karena >>> x = 10 >>> def foo(): .. print(x) .. x += 165 adalah singleton Dalam sebagian besar keadaan lain, tes identitas tidak disarankan dan tes kesetaraan lebih disukai. Khususnya, uji identitas tidak boleh digunakan untuk memeriksa konstanta seperti dan yang tidak dijamin sebagai lajang >>> x = 10 >>> def foo(): .. print(x) .. x += 1_01 Demikian pula, instance baru dari wadah yang dapat berubah tidak pernah identik >>> x = 10 >>> def foo(): .. print(x) .. x += 1_02 Dalam kode pustaka standar, Anda akan melihat beberapa pola umum untuk menggunakan pengujian identitas dengan benar 1) Seperti yang direkomendasikan oleh PEP 8, tes identitas adalah cara yang lebih disukai untuk memeriksa >>> x = 10 >>> def foo(): .. print(x) .. x += 165. Ini berbunyi seperti bahasa Inggris biasa dalam kode dan menghindari kebingungan dengan objek lain yang mungkin memiliki nilai boolean yang bernilai salah 2) Mendeteksi argumen opsional bisa jadi rumit ketika >>> x = 10 >>> def foo(): .. print(x) .. x += 165 adalah nilai input yang valid. Dalam situasi tersebut, Anda dapat membuat objek sentinel tunggal yang dijamin berbeda dari objek lainnya. Misalnya, berikut adalah cara mengimplementasikan metode yang berperilaku seperti >>> x = 10 >>> def foo(): .. print(x) .. x += 1_03 3) Implementasi wadah kadang-kadang perlu menambah tes kesetaraan dengan tes identitas. Ini mencegah kode menjadi bingung oleh objek seperti >>> print(x) 1143 yang tidak sama dengan dirinya sendiri Sebagai contoh, inilah penerapan >>> print(x) 11_44 >>> x = 10 >>> def foo(): .. print(x) .. x += 1_04 Saat mensubklasifikasikan tipe yang tidak dapat diubah, timpa metode alih-alih metode. Yang terakhir hanya berjalan setelah instance dibuat, yang sudah terlambat untuk mengubah data dalam instance yang tidak dapat diubah Semua kelas yang tidak dapat diubah ini memiliki tanda tangan yang berbeda dari kelas induknya >>> x = 10 >>> def foo(): .. print(x) .. x += 1_05 Kelas dapat digunakan seperti ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_06 Dua alat utama untuk metode caching adalah dan. Yang pertama menyimpan hasil di tingkat instance dan yang terakhir di tingkat kelas Pendekatan cached_property hanya berfungsi dengan metode yang tidak menggunakan argumen apa pun. Itu tidak membuat referensi ke instance. Hasil metode yang di-cache hanya akan disimpan selama instance masih hidup Keuntungannya adalah ketika sebuah instance tidak lagi digunakan, hasil metode yang di-cache akan segera dirilis. Kerugiannya adalah jika instans terakumulasi, metode yang terakumulasi juga akan dihasilkan. Mereka bisa tumbuh tanpa terikat Pendekatan lru_cache bekerja dengan metode yang memiliki argumen hashable. Itu membuat referensi ke instance kecuali upaya khusus dilakukan untuk meneruskan referensi yang lemah Keuntungan dari algoritme yang paling jarang digunakan adalah bahwa cache dibatasi oleh ukuran maksimum yang ditentukan. Kerugiannya adalah instans tetap hidup sampai mereka menua dari cache atau sampai cache dibersihkan Contoh ini menunjukkan berbagai teknik >>> x = 10 >>> def foo(): .. print(x) .. x += 1_07 Contoh di atas mengasumsikan bahwa station_id tidak pernah berubah. Jika atribut instance yang relevan dapat diubah, pendekatan cached_property tidak dapat berfungsi karena tidak dapat mendeteksi perubahan pada atribut Agar pendekatan lru_cache berfungsi ketika station_id dapat diubah, kelas perlu menentukan metode and sehingga cache dapat mendeteksi pembaruan atribut yang relevan >>> x = 10 >>> def foo(): .. print(x) .. x += 1_08 Saat modul diimpor untuk pertama kali (atau saat file sumber telah berubah sejak file kompilasi saat ini dibuat) file >>> print(x) 1151 yang berisi kode yang dikompilasi harus dibuat di subdirektori >>> print(x) 1152 dari direktori yang berisi file >>> print(x) 1153. File >>> print(x) 11_51 akan memiliki nama file yang dimulai dengan nama yang sama dengan file >>> print(x) 1153, dan diakhiri dengan >>> print(x) 1151, dengan komponen tengah yang bergantung pada biner >>> print(x) 1157 tertentu yang membuatnya. (Lihat PEP 3147 untuk detailnya. ) Salah satu alasan mengapa file >>> print(x) 11_51 tidak dapat dibuat adalah masalah izin dengan direktori yang berisi file sumber, artinya subdirektori >>> print(x) 1152 tidak dapat dibuat. Ini dapat terjadi, misalnya, jika Anda mengembangkan sebagai satu pengguna tetapi menjalankan sebagai pengguna lain, seperti jika Anda menguji dengan server web Kecuali jika variabel lingkungan disetel, pembuatan a. pyc otomatis jika Anda mengimpor modul dan Python memiliki kemampuan (izin, ruang kosong, dll...) untuk membuat subdirektori >>> print(x) 1152 dan menulis modul yang dikompilasi ke subdirektori tersebut Menjalankan Python pada skrip tingkat atas tidak dianggap sebagai impor dan tidak ada >>> print(x) 1151 yang akan dibuat. Misalnya, jika Anda memiliki modul tingkat atas >>> print(x) 1163 yang mengimpor modul lain >>> print(x) 1164, saat Anda menjalankan >>> print(x) 1165 (dengan mengetikkan >>> print(x) 1166 sebagai perintah shell), >>> print(x) 1151 akan dibuat untuk >>> print(x) 1168 karena >>> print(x) 1168 diimpor, tetapi tidak ada file ______57 Jika Anda perlu membuat file >>> print(x) 11_51 untuk >>> print(x) 1165 – yaitu, membuat file >>> print(x) 1151 untuk modul yang tidak diimpor – Anda dapat menggunakan the and modules Modul dapat mengkompilasi modul apa pun secara manual. Salah satu caranya adalah dengan menggunakan fungsi >>> print(x) 1179 dalam modul itu secara interaktif >>> x = 10 >>> def foo(): .. print(x) .. x += 1_09 Ini akan menulis >>> print(x) 1151 ke >>> print(x) 1152 subdirektori di lokasi yang sama dengan >>> print(x) 1163 (atau Anda dapat menimpanya dengan parameter opsional >>> print(x) 1183) Anda juga dapat secara otomatis mengkompilasi semua file dalam direktori atau direktori menggunakan modul. Anda dapat melakukannya dari prompt shell dengan menjalankan >>> print(x) 1185 dan memberikan jalur direktori yang berisi file Python untuk dikompilasi >>> x = 10 >>> def foo(): .. print(x) .. x += 1_10 Sebuah modul dapat mengetahui nama modulnya sendiri dengan melihat variabel global yang telah ditentukan sebelumnya >>> print(x) 1186. Jika ini memiliki nilai >>> print(x) 11_87, program dijalankan sebagai skrip. Banyak modul yang biasanya digunakan dengan mengimpornya juga menyediakan antarmuka baris perintah atau swa-uji, dan hanya mengeksekusi kode ini setelah memeriksa >>> print(x) 1186 >>> x = 10 >>> def foo(): .. print(x) .. x += 1_11 Misalkan Anda memiliki modul berikut >>> print(x) 11_63 >>> x = 10 >>> def foo(): .. print(x) .. x += 1_12 >>> print(x) 11_90 >>> x = 10 >>> def foo(): .. print(x) .. x += 1_13 Masalahnya adalah juru bahasa akan melakukan langkah-langkah berikut
Langkah terakhir gagal, karena Python belum selesai menafsirkan >>> print(x) 1165 dan kamus simbol global untuk >>> print(x) 1165 masih kosong Hal yang sama terjadi ketika Anda menggunakan >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 11_06, lalu mencoba mengakses >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 1107 dalam kode global Ada (setidaknya) tiga kemungkinan solusi untuk masalah ini Guido van Rossum merekomendasikan untuk menghindari semua penggunaan >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 1108, dan menempatkan semua kode di dalam fungsi. Inisialisasi variabel global dan variabel kelas harus menggunakan konstanta atau fungsi bawaan saja. Ini berarti segala sesuatu dari modul yang diimpor direferensikan sebagai >>> def foo(): .. x = 10 .. def bar(): .. nonlocal x .. print(x) .. x += 1 .. bar() .. print(x) ... >>> foo() 10 1109 Jim Roskind menyarankan melakukan langkah-langkah dalam urutan berikut di setiap modul
Van Rossum tidak terlalu menyukai pendekatan ini karena impor muncul di tempat yang aneh, tetapi berhasil Matthias Urlichs merekomendasikan restrukturisasi kode Anda sehingga impor rekursif tidak diperlukan sejak awal Solusi ini tidak saling eksklusif Pertimbangkan untuk menggunakan fungsi kenyamanan dari sebagai gantinya >>> x = 10 >>> def foo(): .. print(x) .. x += 1_14 Untuk alasan efisiensi dan juga konsistensi, Python hanya membaca file modul saat pertama kali modul diimpor. Jika tidak, dalam program yang terdiri dari banyak modul di mana masing-masing mengimpor modul dasar yang sama, modul dasar akan diurai dan diurai berkali-kali. Untuk memaksa membaca ulang modul yang diubah, lakukan ini >>> x = 10 >>> def foo(): .. print(x) .. x += 1_15 Peringatan. teknik ini tidak 100% anti-bodoh. Secara khusus, modul yang berisi pernyataan seperti >>> x = 10 >>> def foo(): .. print(x) .. x += 1_16 akan terus bekerja dengan versi lama dari objek yang diimpor. Jika modul berisi definisi kelas, instance kelas yang ada tidak akan diperbarui untuk menggunakan definisi kelas yang baru. Hal ini dapat mengakibatkan perilaku paradoks berikut Bagaimana Anda mengubah variabel dalam satu lingkaran dengan Python?Untuk mengubah nama variabel dalam satu lingkaran dengan Python, Anda cukup menugaskan ulang nilai baru ke variabel . Sebagai contoh. untuk saya dalam jangkauan(10). x = saya.
Bisakah Anda mengubah variabel di while loop Python?Tidak seperti pernyataan if, kondisi dalam perulangan while pada akhirnya harus menjadi False. Jika ini tidak terjadi, while loop akan terus berjalan selamanya. Cara terbaik untuk mengubah kondisi dari True ke False adalah dengan menggunakan variabel sebagai bagian dari ekspresi Boolean. Kita kemudian dapat mengubah variabel di dalam while loop .
Bisakah saya memodifikasi variabel loop?Gunakan hanya ekspresi kenaikan dalam perulangan for untuk memodifikasi variabel perulangan , atau ubah ke perulangan while jika perulangan memerlukan iterasi variabel yang lebih rumit.
Apa yang dilakukan += dalam perulangan for?Operator penugasan tambahan ( += ) menambahkan nilai operan kanan ke variabel dan menetapkan hasilnya ke variabel . |