Badan penyata (dengan-badan): Blok kod yang dibalut dalam pernyataan dengan akan memanggil kaedah enter() pengurus konteks sebelum melaksanakan badan pernyataan, dan kaedah exit() akan dilaksanakan selepas badan pernyataan itu dilaksanakan.
Sintaks asas dan prinsip kerja
Format sintaks pernyataan with adalah seperti berikut:
Penyenaraian 1. Format sintaks bagi pernyataan with
with context_expression [as target(s)]:
with-body
Di sini contextexpression mengembalikan objek konteks manager, yang tidak diberikan kepada klausa sebagai Dalam sasaran, jika klausa sebagai ditentukan, nilai pulangan kaedah _enter() pengurus konteks akan diberikan kepada sasaran. sasaran(s) boleh menjadi pembolehubah tunggal, atau tuple yang disertakan dengan "()" (ia tidak boleh menjadi senarai pembolehubah yang dipisahkan hanya dengan ",", "()" mesti ditambah).
Python telah menambah baik beberapa objek terbina dalam dan menambah sokongan untuk pengurus konteks, yang boleh digunakan dengan pernyataan, seperti menutup fail secara automatik, memperoleh dan melepaskan kunci benang secara automatik, dsb. Katakan anda ingin mengendalikan fail, anda boleh menggunakan pernyataan with untuk mempunyai kod berikut:
Penyenaraian 2. Gunakan pernyataan with untuk mengendalikan objek fail
dengan open(r'somefileName' ) sebagai somefile:
untuk baris dalam somefile:
print line
# ...lagi kod
The with pernyataan digunakan di sini, tidak kira apa yang sedang diproses Sama ada pengecualian berlaku semasa proses fail, ia boleh dipastikan bahawa pemegang fail terbuka telah ditutup selepas pernyataan dengan dilaksanakan. Jika anda menggunakan paradigma try/finally tradisional, anda perlu menggunakan kod yang serupa dengan yang berikut:
Penyenaraian 3. Manipulasi objek fail dalam mod try/finally
sesuatu fail = open(r' somefileName')
cuba:
untuk baris dalam somefile:
print line
# ...lagi kod
akhirnya:
somefile.close()
Sebagai perbandingan, menggunakan pernyataan with boleh mengurangkan jumlah pengekodan. Penjalinan modul, perpuluhan, dsb. juga telah ditambahkan untuk menyokong protokol pengurusan konteks.
PEP 0343 menerangkan pelaksanaan pernyataan dengan. Proses pelaksanaan pernyataan with adalah serupa dengan blok kod berikut:
Penyenaraian 4. Proses pelaksanaan pernyataan with
context_manager = context_expression
exit = type(context_manager) .__exit__
Value = type(context_manager).__enter__(context_manager)
exc = True # True bermaksud pelaksanaan biasa, walaupun terdapat pengecualian, ia akan diabaikan; False bermaksud membuang semula pengecualian, dan pengecualian perlu dirawat Proses
cuba:
cuba:
sasaran = nilai # Jika klausa sebagai digunakan
dengan badan # Laksanakan dengan badan
kecuali: # Pengecualian berlaku semasa pelaksanaan
exc = Salah
# Jika __exit__ kembali Benar , pengecualian diabaikan; jika ia mengembalikan False, pengecualian akan dibuang semula
#Pengendalian pengecualian oleh kod luar
jika tidak keluar(context_manager, *sys.exc_info()):
naikkan
akhirnya:
# Keluar seperti biasa, atau keluar melalui penyataan rehat/sambung/balik dalam badan pernyataan
# Atau abaikan pengecualian dan keluar
jika exc:
keluar (context_manager, None, None, None)
# Returns None secara lalai, None dianggap sebagai False dalam konteks Boolean
Laksanakan context_expression untuk menjana context manager context_manager.
Panggil kaedah enter() pengurus konteks; jika klausa as digunakan, tetapkan nilai pulangan kaedah enter() kepada sasaran dalam klausa as.
Badan penyata pelaksanaan dengan-badan
Tidak kira sama ada pengecualian berlaku semasa pelaksanaan, kaedah exit() pengurus konteks pelaksanaan dilaksanakan Exit(). kaedah bertanggungjawab untuk melaksanakan kerja "Pembersihan", seperti mengeluarkan sumber, dsb. Jika tiada pengecualian berlaku semasa pelaksanaan, atau pemecahan penyataan/sambung/kembali dilaksanakan dalam badan penyata, panggil exit(None, None, None) dengan None sebagai parameter jika pengecualian berlaku semasa pelaksanaan, gunakan sys.excinfo The exception maklumat ialah panggilan parameter _exit(exc_type, exc_value, exc_traceback).
Apabila pengecualian berlaku, jika exit(type, value, traceback) mengembalikan False, pengecualian akan dibuang semula, membenarkan logik pernyataan selain daripada mengendalikan pengecualian ini juga ia mengembalikan Benar, kemudian Abaikan pengecualian dan tidak lagi mengendalikan pengecualian.
Pengurus konteks tersuai
Pembangun boleh menyesuaikan kelas yang menyokong protokol pengurusan konteks. Pengurus konteks tersuai perlu melaksanakan kaedah enter() dan exit() yang diperlukan oleh protokol pengurusan konteks:
Contextmanager._enter(): Masukkan konteks masa jalan pengurus konteks dan laksanakannya dalam badan penyata Dipanggil sebelum ini. Pernyataan dengan memberikan nilai pulangan kaedah kepada sasaran dalam klausa sebagai, jika satu dinyatakan.
Contextmanager._exit(exc_type, exc_value, exc_traceback): Keluar daripada konteks masa jalan yang berkaitan dengan pengurus konteks dan kembalikan nilai Boolean yang menunjukkan sama ada untuk mengendalikan pengecualian yang berlaku. Parameter menunjukkan pengecualian yang menyebabkan operasi keluar Jika tiada pengecualian berlaku semasa keluar, ketiga-tiga parameter adalah Tiada. Jika pengecualian berlaku, kembali.
Benar bermaksud tidak mengendalikan pengecualian, jika tidak pengecualian akan dibuang semula selepas keluar daripada kaedah yang akan dikendalikan oleh logik kod di luar pernyataan dengan. Jika pengecualian dibangkitkan dalam kaedah ini, ia akan menggantikan pengecualian yang dibangkitkan oleh pernyataan dalam badan penyata. Apabila mengendalikan pengecualian, jangan buang semula pengecualian secara eksplisit, iaitu, anda tidak boleh membuang semula pengecualian yang dihantar melalui parameter Anda hanya perlu menetapkan nilai pulangan kepada Palsu. Kod pengurusan konteks kemudian mengesan sama ada exit() gagal mengendalikan pengecualian.
Berikut ialah contoh mudah untuk menunjukkan cara membina pengurus konteks tersuai. Ambil perhatian bahawa pengurus konteks mesti memberikan definisi untuk kedua-dua kaedah enter() dan exit(), ketiadaan salah satu daripadanya akan mengakibatkan AttributeError pernyataan dengan terlebih dahulu menyemak sama ada kaedah exit() disediakan, dan kemudian menyemak sama ada enter () kaedah ditakrifkan.
Katakan terdapat sumber DummyResource Sumber ini perlu diperuntukkan sebelum mengakses dan dikeluarkan selepas digunakan Operasi peruntukan boleh diletakkan dalam kaedah enter() dan operasi pelepasan boleh diletakkan di exit(. ) kaedah. Demi kesederhanaan, hanya penyata cetakan digunakan untuk menunjukkan operasi semasa, dan tiada peruntukan dan keluaran sumber sebenar.
Penyenaraian 5. Objek tersuai yang menyokong pernyataan dengan
class DummyResource:
def __init__(self, tag):
Self.tag = tag
cetak 'Resource [%s]' % tag
def __enter__(self):
print '[Enter %s]: Peruntukkan sumber .' % self.tag
return self # Objek yang berbeza boleh dikembalikan
def __exit__(self, exc_type, exc_value, exc_tb):
print '[Exit %s ]: Sumber percuma.' % self.tag
jika exc_tb ialah Tiada:
cetak '[Keluar %s]: Keluar tanpa pengecualian.' % self.tag
else:
print '[Keluar %s]: Keluar dengan pengecualian dinaikkan.' % self.tag
return False # Boleh diabaikan, lalai Tiada juga dianggap sebagai False
Enter() dalam DummyResource mengembalikan rujukan kepada dirinya sendiri, yang boleh diberikan kepada pembolehubah sasaran dalam klausa sebagai; menjadi objek pengurus konteks itu sendiri.
Pembolehubah exctb dikesan dalam kaedah exit() Jika ia bukan Tiada, ini bermakna pengecualian telah berlaku bermakna pengecualian perlu dikendalikan oleh logik kod luaran tiada pengecualian berlaku, lalai Nilai pulangan ialah Tiada, yang juga dianggap sebagai Palsu dalam persekitaran Boolean Walau bagaimanapun, kerana tiada pengecualian berlaku, ketiga-tiga parameter _exit() semuanya Tiada Kod pengurusan konteks boleh mengesan situasi ini dan mengendalikannya secara normal.
Berikut adalah untuk mengakses DummyResource dalam pernyataan with:
Penyenaraian 6. Menggunakan objek tersuai yang menyokong pernyataan with
dengan DummyResource( 'Biasa' ):
cetak '[dengan-badan] Jalankan tanpa pengecualian.'
dengan DummyResource('With-Exception'):
cetak '[dengan- body] Lari dengan pengecualian.'
bangkitkan Exception
cetak '[with-body] Run with exception Gagal menyelesaikan statement-body!'
Perlaksanaan yang pertama. dengan pernyataan Keputusan adalah seperti berikut:
Penyenaraian 7. Dengan pernyataan 1 hasil pelaksanaan
Sumber [Normal]
[Masukkan Normal]: Alokasikan sumber.
[dengan badan] Jalankan tanpa pengecualian.
[Keluar Biasa]: Sumber percuma.
[Keluar Biasa]: Keluar tanpa pengecualian.
Anda boleh lihat, semasa pelaksanaan biasa, badan pernyataan dengan badan akan dilaksanakan terlebih dahulu, dan kemudian kaedah exit() akan dilaksanakan untuk melepaskan sumber.
Keputusan pelaksanaan kedua dengan pernyataan adalah seperti berikut:
Penyenaraian 8. Hasil pelaksanaan dengan pernyataan 2
Sumber [Dengan- Exception]
[Enter With-Exception]: Peruntukkan sumber.
[with-body] Jalankan dengan pengecualian.
[Exit With-Exception]: Sumber percuma.
[Keluar Dengan Pengecualian]: Keluar dengan pengecualian dinaikkan.
Surih balik (panggilan terbaharu terakhir):
Fail "G:/demo", baris 20, dalam kenaikan Pengecualian
Pengecualian
Dapat dilihat bahawa apabila pengecualian berlaku dalam badan dengan badan, dengan badan belum selesai melaksanakan, tetapi sumber dijamin akan dikeluarkan Pada masa yang sama, pengecualian yang dijana disebabkan oleh logik kod di luar pemprosesan tangkapan dengan.
Anda boleh menyesuaikan pengurus konteks untuk mengurus sumber dalam sistem perisian, seperti sambungan pangkalan data, kawalan akses sumber yang dikongsi, dsb. Dokumentasi dalam talian Python Writing Context Managers menyediakan contoh ringkas pengurus konteks untuk menguruskan sambungan pangkalan data.
Modul Contextlib
Modul contextlib menyediakan 3 objek: pengurus konteks penghias, fungsi bersarang dan penutup pengurus konteks. Menggunakan objek ini, anda boleh membungkus fungsi atau objek penjana sedia ada dan menambah sokongan untuk protokol pengurusan konteks, mengelakkan keperluan untuk menulis pengurus konteks secara khusus untuk menyokong pernyataan dengan.
Pengurus konteks penghias
Pengurus Konteks digunakan untuk menghiasi fungsi penjana Selepas fungsi penjana dihias, pengurus konteks dikembalikan, dan kaedah enter() dan exit()nya ialah Pengurus konteks ialah. bertanggungjawab untuk menyediakannya dan bukannya iterator sebelumnya. Fungsi penjana berhias hanya boleh menghasilkan satu nilai, jika tidak, ia akan menyebabkan pengecualian RuntimeError nilai yang dijana akan diberikan kepada sasaran dalam klausa sebagai, jika klausa sebagai digunakan. Mari kita lihat contoh mudah.
Penyenaraian 9. Contoh penggunaan pengurus konteks penghias
daripada pengurus konteks import contextlib
@contextmanager
def demo():
cetak '[Peruntukkan sumber]'
cetak 'Kod sebelum penyata hasil dilaksanakan dalam __enter__'
hasil '*** demo pengurus konteks ***'
cetak 'Kod selepas penyata hasil dilaksanakan dalam __exit__'
cetak '[Sumber percuma]'
dengan demo() sebagai nilai:
cetak 'Nilai Diberikan: % s' % value
Output keputusan adalah seperti berikut:
Penyenaraian 10. Contextmanager penggunaan contoh hasil pelaksanaan
[Peruntukkan sumber]
Kod sebelum penyata hasil dilaksanakan dalam __enter__
Nilai Diberikan: *** demo pengurus konteks ***
Kod selepas penyata hasil dilaksanakan dalam __exit__
Dapat dilihat bahawa pernyataan sebelum hasil dalam fungsi penjana dilaksanakan dalam kaedah enter(), pernyataan selepas hasil dilaksanakan dalam exit(), dan nilai yang dijana oleh hasil diberikan kepada pembolehubah nilai as. Perlu diingatkan bahawa pengurus konteks hanya meninggalkan penulisan enter() / exit(), tetapi tidak bertanggungjawab untuk "pemerolehan" dan "pembersihan" sumber yang perlu dilakukan; ditakrifkan dalam pernyataan hasil Sebelum ini, operasi "pembersihan" diperlukan untuk mentakrifkan pernyataan hasil, supaya pernyataan with akan melaksanakan pernyataan ini untuk mendapatkan/melepaskan sumber apabila melaksanakan kaedah enter() / exit(), iaitu, yang diperlukan kawalan logik, termasuk sumber, perlu dilaksanakan dalam fungsi penjana Lemparkan pengecualian yang sesuai apabila ralat akses berlaku.Fungsi bersarang
bersarang boleh menyusun berbilang pengurus konteks bersama-sama untuk mengelakkan penggunaan bersarang dengan pernyataan.Penyenaraian 11. sintaks bersarang
dengan bersarang(A(), B(), C()) sebagai (X, Y, Z):# kod dengan badan di sini Serupa dengan:
Penyenaraian 12. proses pelaksanaan bersarang
dengan A() sebagai X: dengan B() sebagai Y: dengan C() sebagai Z: # kod dengan badan di sini Perlu diingatkan bahawa pengecualian berlaku Akhirnya, jika kaedah exit() pengurus konteks mengembalikan False untuk pengendalian pengecualian, pengurus konteks luar tidak akan mengesan pengecualian.Penutupan pengurus konteks
Pelaksanaan penutupan adalah seperti berikut:Penyenaraian 13. Pelaksanaan penutupan pengurusan konteks
penutupan kelas(objek): # help doc here def __init__(self, thing): self.thing = thing def __enter__(self): return self.thing def __exit__(self, *exc_info): self.thing.close() konteks Pengurus akan menetapkan objek yang dibalut kepada pembolehubah sasaran klausa sebagai, dan memastikan objek yang dibuka akan ditutup selepas dengan-badan dilaksanakan. Objek yang dibalut oleh pengurus konteks penutup mesti memberikan definisi kaedah close(), jika tidak, AttributeError akan dilaporkan semasa pelaksanaan.Penyenaraian 14. Objek tersuai yang menyokong penutupan
kelas ClosingDemo(objek): def __init__(self): Self.acquire() def acquire(self): print 'Acquire resources.' def free(self): print ' Clean sehingga mana-mana sumber yang diperolehi.' def close(self): self.free() with closing(ClosingDemo()): print 'Menggunakan sumber' Outputnya adalah seperti berikut:Penyenaraian 15. Output objek penutup tersuai
Dapatkan sumber.Menggunakan sumber Bersihkan mana-mana sumber yang diperoleh. Penutupan digunakan untuk objek yang menyediakan pelaksanaan close(), seperti sambungan rangkaian, sambungan pangkalan data, dll. Ia juga boleh diluluskan apabila menyesuaikan kelas Interface close() untuk melaksanakan kerja "pembersihan" sumber yang diperlukan.
Atas ialah kandungan terperinci Bagaimana untuk menggunakan pernyataan Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!