要模拟defer fmt.Println(*a, i)
示例,您可以使用contextlib.ExitStack
:
#!/usr/bin/env python3 from contextlib import ExitStack from functools import partial print("counting") with ExitStack() as stack: for i in range(10): a = i stack.callback(partial(print, a, i)) x = 42 a = x print("done")
counting done 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0
可以轻松模拟互斥锁的情况:
def some_function(lock=Lock()): with lock: # whatever
Python的with语句与Go的延迟具有相似的目的.
Python中类似的代码是:
mutex = Lock() def someFunction(): with mutex: # Whatever you want, with as many return statements # as you want, wherever. Simply forget that you ever # locked a mutex, or that you have to remember to # release it again.
我在那里做了一个(与2.x兼容):
@defers_collector def func(): f = open('file.txt', 'w') defer(lambda: f.close()) defer(lambda : print("Defer called!")) def my_defer(): recover() defer(lambda: my_defer()) print("Ok )") panic("WTF?") print("Never printed (((") func() print("Recovered!")
来源defers_collector
是:
# Go-style error handling import inspect import sys def panic(x): raise Exception(x) def defer(x): for f in inspect.stack(): if '__defers__' in f[0].f_locals: f[0].f_locals['__defers__'].append(x) break def recover(): val = None for f in inspect.stack(): loc = f[0].f_locals if f[3] == '__exit__' and '__suppress__' in loc: val = loc['exc_value'] loc['__suppress__'].append(True) break return val class DefersContainer(object): def __init__(self): # List for sustain refer in shallow clone self.defers = [] def append(self, defer): self.defers.append(defer) def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): __suppress__ = [] for d in reversed(self.defers): try: d() except: __suppress__ = [] exc_type, exc_value, traceback = sys.exc_info() return __suppress__ def defers_collector(func): def __wrap__(*args, **kwargs): __defers__ = DefersContainer() with __defers__: func(*args, **kwargs) return __wrap__
一个延迟部分的灵感来自于实施@DenisKolodin 答案是可以作为的一部分pygolang,2:
wc = wcfs.join(zurl) ? wc = wcfs.join(zurl) defer(wc.close) ? try: ? ... ... ? ... ... ? ... ... ? finally: ? wc.close()