Maison >développement back-end >Tutoriel Python >Explication détaillée de l'utilisation du mot-clé with en Python
Cet article présente principalement des informations pertinentes sur l'utilisation détaillée du mot-clé with en Python En Python, le mot-clé with est une bonne chose pour gérer l'implémentation des objets de protocole contextuel pour vous. it Vous pouvez vous référer à ce qui suit
">
Dans Python 2.5, le mot-clé with a été ajouté. Il rend le modèle try ... except ... enfin ... couramment utilisé Réutilisation très pratique. Regardez l'exemple le plus classique :
with open('file.txt') as f: content = f.read()
Dans ce code, peu importe ce qui se passe lors de l'exécution du bloc de code dans with, le fichier sera finalement fermé si une exception se produit pendant. exécution, le programme fermera d'abord le fichier ouvert avant que l'exception ne soit levée.
Regardez un autre exemple avant de lancer une base de données. Lors des demandes de transaction, un code similaire à celui-ci est souvent utilisé :
.
Si l'opération de lancement d'une demande de transaction est modifiée pour prendre en charge le mot-clé with, alors un code comme celui-ci suffit :db.begin() try: # do some actions except: db.rollback() raise finally: db.commit()Le processus d'exécution de with est expliqué en détail, et le code ci-dessus est implémenté de deux manières courantes.
with transaction(db): # do some actionsLe processus général d'exécution de with
Une base avec
expression, sa structure est la suivante : où : EXPR peut être n'importe quelle expression ; car VAR est facultatif pour son exécution générale. Le processus est le suivant :
with EXPR as VAR: BLOCKCalculez EXPR et obtenez un gestionnaire de contexte.
Ce processus a plusieurs détails :
mgr = (EXPR) exit = type(mgr).exit # 这里没有执行 value = type(mgr).enter(mgr) exc = True try: try: VAR = value # 如果有 as VAR BLOCK except: exc = False if not exit(mgr, *sys.exc_info()): raise finally: if exc: exit(mgr, None, None, None)
Implémentez la classe du gestionnaire de contexte
La première façon consiste à implémenter une classe qui contient une instance
attributs
Après avoir compris le processus d'exécution de with, cette implémentation est facile à comprendre. La méthode de mise en œuvre présentée ci-dessous est beaucoup plus compliquée à comprendre.
Utilisation de Générateurs
Décorateursclass transaction(object): def init(self, db): self.db = db def enter(self): self.db.begin() def exit(self, type, value, traceback): if type is None: db.commit() else: db.rollback()Dans la bibliothèque standard de Python, il existe un décorateur qui peut obtenir un gestionnaire de contexte via un générateur. Le processus d'implémentation à l'aide du générateur décorateur est le suivant :
Une fois que l'interpréteur Python a reconnu le mot-clé rendement, def créera une
fonction génératricefrom contextlib import contextmanager @contextmanager def transaction(db): db.begin() try: yield db except: db.rollback() raise else: db.commit()pour remplacer la fonction régulière (dans le définition de classe (j'aime utiliser des fonctions plutôt que des méthodes).
with 表达式调用实例对象的上下文管理器的 enter() 方法。
enter() 方法中会调用这个生成器的 next() 方法。这时候,生成器方法会执行到 yield db 处停止,并将 db 作为 next() 的返回值。如果有 as VAR ,那么它将会被赋值给 VAR 。
with 中的 BLOCK 被执行。
BLOCK 执行结束后,调用上下文管理器的 exit() 方法。 exit() 方法会再次调用生成器的 next() 方法。如果发生 StopIteration 异常,则 pass 。
如果没有发生异常生成器方法将会执行 db.commit() ,否则会执行 db.rollback() 。
再次看看上述过程的代码大致实现:
def contextmanager(func): def helper(*args, **kwargs): return GeneratorContextManager(func(*args, **kwargs)) return helper class GeneratorContextManager(object): def init(self, gen): self.gen = gen def enter(self): try: return self.gen.next() except StopIteration: raise RuntimeError("generator didn't yield") def exit(self, type, value, traceback): if type is None: try: self.gen.next() except StopIteration: pass else: raise RuntimeError("generator didn't stop") else: try: self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration: return True except: if sys.exc_info()[1] is not value: raise
总结
Python的 with 表达式包含了很多Python特性。花点时间吃透 with 是一件非常值得的事情。
一些其他的例子
锁机制
@contextmanager def locked(lock): lock.acquired() try: yield finally: lock.release()
标准输出重定向
@contextmanager def stdout_redirect(new_stdout): old_stdout = sys.stdout sys.stdout = new_stdout try: yield finally: sys.stdout = old_stdout with open("file.txt", "w") as f: with stdout_redirect(f): print "hello world"
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!