Artikel ini memfokuskan pada penjelasan dan aplikasi pengurusan konteks dalam Python. Atau melalui contoh kod, pemahaman dan pembelajaran perbandingan, untuk mencapai pemahaman, penguasaan dan aplikasi "lebih laju, ekonomi yang lebih baik". Tanpa berlengah lagi, mari kita mulakan——
Pengurus konteks ialah objek yang mentakrifkan pengurus konteks yang akan dibuat semasa melaksanakan? a dengan konteks masa jalan. Pengurus konteks ialah masa jalan yang secara automatik mengendalikan kemasukan dan keluar untuk konteks di mana blok kod dilaksanakan. Pengurus konteks biasanya dipanggil menggunakan pernyataan dengan, tetapi juga boleh digunakan dengan memanggil kaedah mereka secara langsung.
Penggunaan biasa pengurus konteks termasuk menyimpan dan memulihkan pelbagai keadaan global, mengunci dan membuka kunci sumber, menutup fail terbuka dan banyak lagi.
Dalam bab ini, kita akan belajar cara menggunakan pengurus konteks dalam Python dan cara menyesuaikan pengurus konteks.
Pernyataan dengan digunakan untuk melaksanakan blok pembalut kaedah yang ditakrifkan oleh pengurus konteks. Ini membolehkan untuk merangkum percubaan biasa...kecuali...akhirnya corak penggunaan untuk mudah digunakan semula. Pernyataan dengan memberikan kod yang lebih pendek dan boleh digunakan semula berbanding dengan percubaan tradisional...kecuali...akhirnya sekat.
Dalam perpustakaan standard Python, banyak kelas menyokong pernyataan dengan. Contoh yang sangat biasa ialah fungsi open() terbina dalam, yang menyediakan corak untuk memproses objek fail menggunakan pernyataan with.
Berikut ialah sintaks umum pernyataan dengan:
with expression as target: # 使用target # 来处理事情
Mari kita lihat contoh penggunaan fungsi open(). Terdapat fail teks dalam folder fail projek semasa. Nama fail ialah color_names.txt, yang mengandungi beberapa nama warna (anda boleh menyediakan beberapa kandungan teks sendiri). Kami ingin membuka dan mencetak kandungan fail ini dengan menggunakan fungsi open() dan pernyataan dengan. Contoh kod adalah seperti berikut:
import os fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep #自定义文件路径 # 指定文件路径和名称 path = fileDirPath+'files/color_names.txt' # with 语句 with open(path, mode='r') as file: # 读取文件内容 print(file.read())
Hasil output menjalankan program adalah seperti berikut
red orange yellow green blue white black
Dalam senarai di atas, perkara yang anda lihat ialah kes penggunaan biasa bagi dengan kenyataan. Kami menggunakan fungsi open() untuk membuka fail pada laluan (path) yang diberikan dan fungsi open() mengembalikan objek fail dalam mod baca sahaja. Kod kemudian menggunakan objek fail ini untuk membaca dan mencetak kandungannya melalui kod: print(file.read()).
Contoh di atas ialah penggunaan biasa pengurus konteks. Untuk lebih memahami dan menggunakan pengurus konteks, kita perlu terus membaca.
Protokol Pengurus Konteks, secara terang-terangan, ialah mekanisme pemprosesan pengurus konteks, atau piawaian protokol yang telah ditetapkan. Bahagian ini juga boleh didapati di sini: Python Core Protocol. Demi kemerdekaan membaca, mari kita bincangkan semula di sini.
Pernyataan Python dengan menyokong konsep konteks masa jalan yang ditakrifkan oleh pengurus konteks. Ini dicapai melalui sepasang kaedah yang membenarkan kelas yang ditentukan pengguna untuk menentukan konteks masa jalan yang dimasukkan sebelum badan pernyataan dilaksanakan dan keluar pada penghujung pernyataan.
Kaedah yang dinyatakan di atas dipanggil protokol pengurus konteks. Mari lihat kedua-dua kaedah ini secara terperinci:
1) __enter__(self)
Kaedah ini dipanggil dengan pernyataan with untuk memasuki konteks runtime yang berkaitan dengan arus objek . Pernyataan dengan mengikat nilai pulangan kaedah ini kepada sasaran (jika ada) yang dinyatakan dalam klausa sebagai klausa.
Pengurus konteks yang dikembalikan dalam contoh di atas ialah objek fail. Di sebalik tabir, objek fail mengembalikan dirinya sendiri daripada __enter__() untuk membenarkan open() digunakan sebagai ungkapan kontekstual dalam pernyataan dengan.
2) __exit__(self, exc_type, exc_value, traceback):
Kaedah ini dipanggil apabila pelaksanaan meninggalkan blok kod dengan. Ia keluar dari konteks masa jalan yang dikaitkan dengan objek ini. Parameter menerangkan maklumat pengecualian yang menyebabkan konteks keluar. Jika konteks keluar tanpa pengecualian, ketiga-tiga parameter akan menjadi Tiada.
Jika pengecualian disediakan dan kaedah dijangka menyekat pengecualian (iaitu, menghalangnya daripada disebarkan), maka ia harus mengembalikan nilai Benar. Jika tidak, pengecualian akan dikendalikan seperti biasa apabila keluar daripada kaedah ini. Kaedah __exit__() mengembalikan nilai Boolean, yang boleh menjadi Benar atau Salah.
Proses melaksanakan pernyataan dengan menggunakan kaedah dalam protokol pengurus konteks adalah seperti berikut:
with EXPRESSION as TARGET: SUITE
Jika suite keluar atas apa-apa sebab selain daripada pengecualian, nilai pulangan __exit__() diabaikan dan pelaksanaan kod berikutnya (jika ada) diteruskan di lokasi biasa untuk jenis keluar yang sedang dilaksanakan .
Sekarang kita memahami idea asas di sebalik protokol pengurus konteks, mari kita laksanakannya dalam kelas. Kelas ini akan menjadi pengurus konteks kami dan kami akan menggunakannya kemudian dalam pernyataan dengan.
定义的上下文管理器类参考示例清单如下:
# 自定义上下文管理器类 class CustomContextManager: # 初始化方法init -> 定义一些变量 def __init__(self, path, mode): self.path = path self.mode = mode self.file = None # __enter__ method -> open the file def __enter__(self): self.file = open(self.path, self.mode) return self.file # exit method to close the file def __exit__(self, exc_type, exc_value,exc_traceback): self.file.close()
我们的CustomContextManager类实现了成为上下文管理器的必要方法:__enter__和__exit__。
在__init__方法中,它定义了三个实例变量来存储路径、模式和文件对象。
在__enter__方法中,它使用内置的open()函数打开指定路径中的文件。由于open()函数返回file对象,我们将其赋值给self.file属性。
在__exit__方法中,我们将文件关闭:self.file.close()。
__exit__方法接受三个参数,它们是上下文管理器协议所需要的。
现在我们可以在with语句中使用自定义上下文管理器。
使用自定义的类上下文管理器的示例(和我们前面的示例雷同):
# 应用示例 import os fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep # 在with语句中使用自定义上下文管理器 file_path = fileDirPath + 'files/color_names.txt' with CustomContextManager(path=file_path, mode='r') as file: #输出文件file内容 print(file.read())
运行输出结果这里不再赘述。简单解释一下代码。
上面清单中,在with语句中使用CustomContexManager类,通过它来读取文件内容并打印出来。下面是这个自定义上下文管理器幕后的故事:
1)在with行,调用类CustomContextManager的方_enter__法
2) __enter__方法打开文件并返回它。
3)我们将打开的文件简单地命名为file。
4)在with语句块中,读取文件内容并将其打印出来。
5)with语句自动调用__exit__方法。
6)__exit__方法关闭文件。
我们再来定义另一个上下文管理器类。这次我们想打印指定文件夹中的文件列表。
参考实现的代码清单如下:
class ContentList: '''Prints the content of a directory''' def __init__(self, directory): self.directory = directory def __enter__(self): return os.listdir(self.directory) def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: print("Error getting directory list.") return True # 输出项目目录下的内容 project_directory = '.' with ContentList(project_directory) as directory_list: print(directory_list)
在代码清单中,我们定义了一个新的上下文管理器。这个类的名字是ContentList。为什么它是一个上下文管理器?因为它实现了上下文管理器协议(__enter__和__exit__方法)。
我们将目录路径作为类构造函数__init__方法中的参数。
在__enter__方法中,只需调用os模块中的listdir()方法,就可以获得该目录中的内容列表:os.listdir(self.directory)。然后返回这个列表。请注意,在这个上下文管理器中我们的__enter__方法返回一个列表。
在__exit__方法中,我们检查是否存在任何错误。如果我们的上下文管理器中有错误,exc_type、exc_val、exc_tb参数值将不会为None。因此,我们检查exc_type是否为None以打印错误文本。
在with语句中使用该上下文管理器。由于它返回一个列表对象,我们只需将返回值赋值给directory_list变量。在with语句的主体中,我们打印这个列表。运行程序后在输出中,可以看到项目目录中的内容列表。记住,"."表示当前目录,在我们的例子中是项目根目录(由于项目环境不同,输出内容可能也不一样)。
前文中,我们学习了如何使用类语法定义上下文管理器。但是有点繁琐和冗长。因为需要明确地实现__enter__和exit__方法,还需要处理可能的异常。所以希望Python中能有在创建上下文管理器更好的方法:基于函数的上下文管理器。
其实函数上下文管理器是使用生成器和contextlib.contextmanager装饰器的特殊函数。 contextlib.contextmanager装饰器负责实现上下文管理器协议。
下面就来定义一个函数型上下文管理器。
from contextlib import contextmanager # 定义上下文管理器函数 @contextmanager def function_based_context_manager(): print("进入上下文: __enter__") yield "这是个基于上下文管理器的函数" print("离开上下文: __exit__") # with语句中使用上下文管理器函数 with function_based_context_manager() as yield_text: print(yield_text)
运行程序输出结果类似如下:
进入上下文: __enter__ 这是个基于上下文管理器的函数 离开上下文: __exit__
在上面代码中,我们定义了一个作为上下文管理器的自定义函数。contextmanager装饰器将常规函数转换为全堆栈上下文管理器(自动实现上下文管理器的协议)。如果你为函数提供了@contextmanager装饰器,就不需要担心实现__enter__和__exit__函数。
代码中的yield语句在基于类的上下文管理器中的__enter__方法中充当返回语句。由于我们使用了yield语句,故此,这个基于函数的上下文管理器也是生成器函数。
再来定义一个新的上下文管理器。这一次,它将以写的模式打开一个文件并添加一些文本。示例如下:
在清单中,我们定义了一个基于函数的上下文管理器。在try块中,它尝试打开指定路径中的文件,并指定了文件的默认编码集。如果它成功地打开它,那么它将生成(返回)file_object。在finally块中,我们检查是否有一个file_object要关闭。如果file_object不是None,则关闭file_object。
Dalam pernyataan dengan, kami memanggil pengurus konteks dengan nama fail funBasedContextManagers.txt. Pengurus konteks membuka fail dalam mod tulis dan mengembalikan objek fail, yang kami namakan fail sahaja. Kemudian tulis beberapa teks ke dalam fail ini. Ingat, mod 'w' akan mencipta fail kosong jika fail sedemikian tidak wujud.
Jalankan program di atas Jika fail tidak wujud, hasilkan fail dengan nama yang sepadan dan simpan kandungan bertulis. Jika fail itu wujud, kandungan ditulis ke fail sumber setiap kali Sila beri perhatian kepada operasi ini.
Untuk mengendalikan kerja "penyelesaian" seperti ini, amat mudah untuk menggunakan pengurus konteks, terutamanya apabila melibatkan operasi pangkalan data, contohnya, anda boleh membungkusnya sendiri untuk menutup sambungan secara automatik, dsb.
Dalam isu ini kami memperkenalkan kandungan pengaturcaraan yang berkaitan dengan pengurus konteks, seperti cara mencipta pengurus konteks, protokol pengurus konteks, pengurus konteks bentuk kelas tersuai dan jenis fungsi Pengurus konteks dsb. Kebanyakan kandungan yang berkaitan ditunjukkan dan dijelaskan dengan kod praktikal. Jika anda ingin meningkatkan kemahiran pengaturcaraan anda, menaip kod dengan tangan anda adalah keperluan penting.
Atas ialah kandungan terperinci Pengaturcaraan Python: Mudah Memahami Pengurus Konteks (Pengurus Konteks). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!