Python 2.4中yield在带finally的try块中不允许的解决方法
我现在在用python2.4,所以不能在生成器或者yield
中使用finally语句。有没有什么办法可以解决这个问题呢?
我找不到关于如何绕过python 2.4这个限制的资料,而且我想到的一些解决办法(主要是用__del__
,并试图确保它在合理的时间内运行)也不是很吸引人。
2 个回答
3
当一个生成器实例被简单地放弃(也就是被垃圾回收)时,唯一能保证被调用的代码是它的局部变量的 __del__
方法(如果在外面没有对这些对象的引用)和对它的局部变量的弱引用的回调(同样的道理)。我建议使用弱引用的方法,因为它不会干扰其他代码(你不需要一个特别的类来使用 __del__
,只要是可以被弱引用的对象就行)。例如:
import weakref
def gen():
x = set()
def finis(*_):
print 'finis!'
y = weakref.ref(x, finis)
for i in range(99):
yield i
for i in gen():
if i>5: break
这段代码确实会打印出 finis!
,正如我们所希望的那样。
7
你可以复制代码来避免使用finally块:
try:
yield 42
finally:
do_something()
变成:
try:
yield 42
except: # bare except, catches *anything*
do_something()
raise # re-raise same exception
do_something()
(我没有在Python 2.4上试过,你可能需要查看sys.exc_info,而不是上面提到的重新抛出语句,像这样raise sys.exc_info[0], sys.exc_info[1], sys.exc_info[2]
。)