简短的回答:(在某种程度上)是可能的,但根本不建议这样做。
with
Python 中的部分没有专门的作用域,这意味着语句中定义的变量不会被删除。with
这是经常想要的行为。例如,如果你加载一个文件,你可以这样写:
with open('foo.txt') as f:
data = list(f)
print(data)
您不想删除该data
变量:with
这里用于确保文件处理程序已正确关闭(并且如果 的主体中发生异常,该处理程序也将关闭with
)。
严格来说,您可以通过“hackish”解决方案删除引用该对象的局部变量A()
:我们检查调用堆栈,并删除对self
(或另一个对象)的引用,例如:
import inspect
class A(object):
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
locs = inspect.stack()[1][0].f_locals
ks = [k for k, v in locs.items() if v is self]
for k in ks:
del locs[k]
然后它会像这样删除它:
>>> with A() as a:
... pass
...
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
但我强烈反对这种做法。首先,如果变量是全局的,或者位于本地范围之外,它不会在这里被删除(我们可以解决这个问题,但它会引入很多额外的逻辑)。
此外,甚至没有说变量存在,如果变量是可迭代的,则可以将其定义为:
# If A.__enter__ returns an iterable with two elements
with A() as (foo, bar):
pass
那么这些元素将不会被回收。最后,如果__enter__
返回self
,它可能“删除太多”,因为一个人可以写with foo as bar
,然后两者foo
和bar
都将被删除。
__exit__
无论如何,大多数 IDE 可能无法理解a
.
通常,最好将对象简单地标记为关闭,例如:
import inspect
class A(object):
def __init__(self):
self.closed = False
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.closed = True
def some_method(self):
if self.closed:
raise Exception('A object is closed')
# process request
以上也是文件处理程序的处理方式。