The __debug__
variabel berguna sebagian karena mempengaruhi setiap modul. Jika saya ingin membuat variabel lain yang bekerja dengan cara yang sama, bagaimana saya melakukannya?
Variabel (mari kita menjadi orisinal dan menyebutnya 'foo') tidak harus benar-benar global, dalam artian jika saya mengubah foo dalam satu modul, itu diperbarui di modul lain. Saya akan baik-baik saja jika saya dapat mengatur foo sebelum mengimpor modul lain dan kemudian mereka akan melihat nilai yang sama untuknya.
hasattr(__builtin__, "foo")
.Jika Anda memerlukan variabel lintas-modul global mungkin hanya variabel tingkat modul global yang sederhana sudah cukup.
a.py:
b.py:
c.py:
Uji:
Contoh dunia nyata: global_settings.py Django (meskipun dalam pengaturan aplikasi Django digunakan dengan mengimpor objek
django.conf.settings
).sumber
a.py
, berisimain()
? Apakah itu penting?if __name__=="__main__"
pelindung di dalamnya untuk menghindari menjalankan kode tak terduga saat impor.id()
untuk memeriksa identitas)Saya percaya bahwa ada banyak keadaan di mana itu masuk akal dan menyederhanakan pemrograman untuk memiliki beberapa global yang dikenal di beberapa modul (berpasangan erat). Dalam semangat ini, saya ingin menguraikan sedikit tentang gagasan memiliki modul global yang diimpor oleh modul-modul yang perlu direferensikan.
Jika hanya ada satu modul, saya beri nama "g". Di dalamnya, saya menetapkan nilai default untuk setiap variabel yang ingin saya perlakukan sebagai global. Di setiap modul yang menggunakan salah satunya, saya tidak menggunakan "from g import var", karena ini hanya menghasilkan variabel lokal yang diinisialisasi dari g hanya pada saat impor. Saya membuat sebagian besar referensi dalam bentuk g.var, dan "g". berfungsi sebagai pengingat bahwa saya berurusan dengan variabel yang berpotensi dapat diakses oleh modul lain.
Jika nilai variabel global seperti itu akan sering digunakan dalam beberapa fungsi dalam modul, maka fungsi itu dapat membuat salinan lokal: var = g.var. Namun, penting untuk disadari bahwa penugasan ke var bersifat lokal, dan global g.var tidak dapat diperbarui tanpa merujuk g.var secara eksplisit dalam penugasan.
Perhatikan bahwa Anda juga dapat memiliki beberapa modul global yang dibagikan oleh subset berbeda dari modul Anda untuk menjaga agar hal-hal sedikit lebih terkontrol dengan ketat. Alasan saya menggunakan nama pendek untuk modul global saya adalah untuk menghindari kode yang terlalu berantakan dengan kemunculannya. Dengan hanya sedikit pengalaman, mereka menjadi cukup mnemonik dengan hanya 1 atau 2 karakter.
Masih dimungkinkan untuk membuat penugasan ke, katakanlah, gx ketika x belum didefinisikan dalam g, dan modul lain kemudian dapat mengakses gx Namun, meskipun penerjemah mengizinkannya, pendekatan ini tidak begitu transparan, dan saya menghindari Itu. Masih ada kemungkinan secara tidak sengaja membuat variabel baru di g karena salah ketik pada nama variabel untuk tugas. Kadang-kadang pemeriksaan dir (g) berguna untuk menemukan nama-nama kejutan yang mungkin muncul karena kecelakaan tersebut.
sumber
Definisikan modul (sebut saja "globalbaz") dan tetapkan variabel di dalamnya. Semua modul yang menggunakan "pseudoglobal" ini harus mengimpor modul "globalbaz", dan merujuknya menggunakan "globalbaz.var_name"
Ini berfungsi terlepas dari tempat perubahan, Anda dapat mengubah variabel sebelum atau setelah impor. Modul yang diimpor akan menggunakan nilai terbaru. (Saya menguji ini dalam contoh mainan)
Untuk klarifikasi, globalbaz.py terlihat seperti ini:
sumber
Anda dapat meneruskan global dari satu modul ke modul lainnya:
Di Modul A:
Di Modul B:
sumber
Variabel global biasanya merupakan ide yang buruk, tetapi Anda dapat melakukannya dengan menetapkan ke
__builtins__
:Selain itu, modul itu sendiri adalah variabel yang dapat Anda akses dari modul apa pun. Jadi jika Anda mendefinisikan modul yang disebut
my_globals.py
:Kemudian Anda juga dapat menggunakannya dari mana saja:
Menggunakan modul daripada memodifikasi
__builtins__
umumnya merupakan cara yang lebih bersih untuk melakukan global semacam ini.sumber
__builtins__
adalah kekhasan CPython, Anda seharusnya tidak menggunakannya - gunakan lebih baik__builtin__
(ataubuiltins
di Python3) seperti yang ditunjukkan jawaban yang diterimaAnda sudah dapat melakukan ini dengan variabel tingkat modul. Modul tetap sama tidak peduli dari modul mana mereka diimpor. Jadi, Anda dapat menjadikan variabel sebagai variabel tingkat modul dalam modul apa pun yang masuk akal untuk dimasukkan, dan mengaksesnya atau menetapkannya dari modul lain. Akan lebih baik untuk memanggil fungsi untuk menyetel nilai variabel, atau menjadikannya properti dari beberapa objek tunggal. Dengan cara itu jika Anda akhirnya perlu menjalankan beberapa kode ketika variabel berubah, Anda dapat melakukannya tanpa merusak antarmuka eksternal modul Anda.
Biasanya ini bukan cara yang bagus untuk melakukan sesuatu - menggunakan global jarang - tapi menurut saya ini adalah cara terbersih untuk melakukannya.
sumber
Saya ingin memposting jawaban bahwa ada kasus di mana variabel tidak akan ditemukan.
Impor siklis dapat merusak perilaku modul.
Sebagai contoh:
first.py
second.py
main.py
Pada contoh ini, seharusnya sudah jelas, tetapi dalam basis kode yang besar, ini bisa sangat membingungkan.
sumber
Ini terdengar seperti memodifikasi
__builtin__
ruang nama. Untuk melakukannya:Jangan gunakan
__builtins__
langsung (perhatikan "s" tambahan) - tampaknya ini bisa berupa kamus atau modul. Terima kasih kepada ΤΖΩΤΖΙΟΥ karena telah menunjukkan hal ini, lebih banyak lagi dapat ditemukan di sini .Sekarang
foo
tersedia untuk digunakan di mana saja.Saya tidak menyarankan melakukan ini secara umum, tetapi penggunaan ini terserah programmer.
Menetapkannya harus dilakukan seperti di atas, pengaturan
foo = 'some-other-value'
hanya akan mengaturnya di namespace saat ini.sumber
Saya menggunakan ini untuk beberapa fungsi primitif built-in yang saya rasa benar-benar hilang. Salah satu contohnya adalah fungsi find yang memiliki penggunaan semantik yang sama seperti filter, map, reduce.
Setelah ini dijalankan (misalnya, dengan mengimpor di dekat titik masuk Anda) semua modul Anda dapat menggunakan find () seolah-olah, tentu saja, itu sudah terpasang.
Catatan: Anda dapat melakukan ini, tentu saja, dengan filter dan garis lain untuk menguji panjang nol, atau dengan pengurangan dalam satu jenis garis yang aneh, tetapi saya selalu merasa itu aneh.
sumber
Saya dapat mencapai variabel lintas modul yang dapat dimodifikasi (atau dapat diubah ) dengan menggunakan kamus:
Saat meluncurkan
test_wait_app_up_fail
, durasi waktu tunggu yang sebenarnya adalah 3 detik.sumber
Saya bertanya-tanya apakah mungkin untuk menghindari beberapa kerugian menggunakan variabel global (lihat misalnya http://wiki.c2.com/?GlobalVariablesAreBad ) dengan menggunakan namespace kelas daripada namespace global / modul untuk meneruskan nilai variabel . Kode berikut menunjukkan bahwa kedua metode pada dasarnya identik. Ada sedikit keuntungan dalam menggunakan ruang nama kelas seperti yang dijelaskan di bawah ini.
Fragmen kode berikut juga menunjukkan bahwa atribut atau variabel dapat dibuat dan dihapus secara dinamis di ruang nama global / modul dan ruang nama kelas.
wall.py
Saya menyebut modul ini 'dinding' karena digunakan untuk memantulkan variabel. Ini akan bertindak sebagai ruang untuk sementara mendefinisikan variabel global dan atribut kelas-kelas dari 'router' kelas kosong.
source.py
Modul ini mengimpor dinding dan mendefinisikan satu fungsi
sourcefn
yang mendefinisikan pesan dan memancarkannya dengan dua mekanisme berbeda, satu melalui global dan satu melalui fungsi router. Perhatikan bahwa variabelwall.msg
danwall.router.message
didefinisikan di sini untuk pertama kalinya di ruang nama masing-masing.dest.py
Modul ini mendefinisikan fungsi
destfn
yang menggunakan dua mekanisme berbeda untuk menerima pesan yang dipancarkan oleh sumber. Ini memungkinkan kemungkinan bahwa variabel 'msg' mungkin tidak ada.destfn
juga menghapus variabel setelah ditampilkan.main.py
Modul ini memanggil fungsi yang telah ditentukan sebelumnya secara berurutan. Setelah panggilan pertama ke
dest.destfn
variabelwall.msg
danwall.router.msg
tidak ada lagi.Output dari program ini adalah:
global: Halo dunia!
router: Halo dunia!
global: tidak ada
router pesan : tidak ada pesan
Fragmen kode di atas menunjukkan bahwa modul / global dan mekanisme variabel kelas / kelas pada dasarnya identik.
Jika banyak variabel yang akan dibagikan, polusi namespace dapat dikelola baik dengan menggunakan beberapa modul tipe dinding, misalnya wall1, wall2 dll. Atau dengan mendefinisikan beberapa kelas tipe router dalam satu file. Yang terakhir ini sedikit lebih rapi, jadi mungkin mewakili keuntungan marjinal untuk penggunaan mekanisme variabel kelas.
sumber