Python 使用语句,自动删除对象

Python 使用语句,自动删除对象,python,with-statement,object-destruction,Python,With Statement,Object Destruction,是否可以删除其类中的对象窗体 class A(): def __init__(self): print("init") self.b="c" def __enter__(self): print("enter") return self def __exit__(self, type, value, traceback): print("exit") with A() as a:

是否可以删除其类中的对象窗体

class A():
    def __init__(self):
        print("init")
        self.b="c"
    def __enter__(self):
        print("enter")
        return self
    def __exit__(self, type, value, traceback):
        print("exit")      

with A() as a:
    print(a.b)
print(a.b)
返回:

init
enter
c
exit
c

在使用退出后,我如何仍然可以访问对象?是否有方法自动删除
\uuu exit\uuu
中的对象?

是和否。在
with
子句后面使用
dela
。这将删除对象上最后一个引用持有者的变量
a

对象本身(即在
\uuuuu exit\uuuu()
中)不能让知道它并持有引用的人(即
with
子句中的代码)忘记这一点。只要引用存在,对象就会存在

当然,您的对象可以在
\uuuu exit\uuuu()
中清空自身,并保持为空心对象(例如,在本例中,通过
del self.b

不能在
\uuuu exit\uuuu
中删除类A本身的实例。您最多只能删除属性
b

init
enter
c
exit
Traceback (most recent call last):
  File "main.py", line 14, in <module>
    print(a.b)
AttributeError: A instance has no attribute 'b'
init
进入
C
出口
回溯(最近一次呼叫最后一次):
文件“main.py”,第14行,在
印刷品(a.b)
AttributeError:实例没有属性“b”

简短回答:这(在某种程度上)是可能的,但根本不可取

Python中的
with
部分没有专用的作用域,因此这意味着
with
语句中定义的变量不会被删除。这是经常需要的行为。例如,如果加载一个文件,您可以这样编写:

with open('foo.txt') as f:
    data = list(f)

print(data)
>>> 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
您不想删除
数据
变量:此处使用
with
来确保文件处理程序正确关闭(如果
with
的主体中发生异常,处理程序也会关闭)

严格来说,您可以通过“黑客”解决方案删除引用
A()
对象的局部变量:我们检查调用堆栈,删除对
self
(或其他对象)的引用,如:

因此,这些元素将不会得到回收。最后,如果
\uuuuu enter\uuuuuu
返回
self
,则它可能“删除太多”,因为可以使用foo作为bar编写
,然后
foo
bar
都将被删除

无论如何,大多数IDE可能无法理解
\uuuuu exit\uuuuu
中的逻辑,因此仍然会在自动完成中包含
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

上述也是文件处理程序处理它的方式。

带有的
没有定义特定的范围,因此您可以在定义变量后使用这些变量。是的,但是在退出时不可能这样做吗?如果用户只能用“with”打开我的应用程序,而没有访问权限,那么对我的应用程序来说会更安全afterward@RémiBaudoux:您可以更改对象的状态,使其不再“可访问”(就像文件处理程序一样,在
with
语句中,文件处理程序关闭,但变量仍然存在),删除itI实际上是有道理的,你必须“在”对象之外。我刚刚注意到,你甚至可以在exit中删除方法,这很有用,不是删除,而是通过执行以下操作来禁用访问:
self.my_method=None
谢谢你的准确性!我想我会删除出口中的所有变量和方法,例如,如果我试图访问类中的任何内容,它本身会引发错误。@RémiBaudoux,但请注意,这不是非常Pythonic的。下一个开发人员(或库的用户)可能会对这种行为感到非常惊讶。
# If A.__enter__ returns an iterable with two elements

with A() as (foo, bar):
    pass
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