Python';与';不删除对象

Python';与';不删除对象,python,with-statement,Python,With Statement,正在尝试正确删除Python对象。我正在创建一个对象,然后用“with”语句删除它。但当我在“with”语句关闭后打印时。。。。该对象仍然存在: class Things(object): def __init__(self, clothes, food, money): self.clothes = clothes self.food = food self.money = money def __enter__(self):

正在尝试正确删除Python对象。我正在创建一个对象,然后用“with”语句删除它。但当我在“with”语句关闭后打印时。。。。该对象仍然存在:

class Things(object):
   def __init__(self, clothes, food, money):
       self.clothes = clothes
       self.food = food
       self.money = money

   def __enter__(self):
       return self

   def __exit__(self, exc_type, exc_val, exc_tb):
       print('object deleted')

with Things('socks','food',12) as stuff:
    greg = stuff.clothes
    print(greg)


print(stuff.clothes)
返回:

socks
object deleted
socks

with
在退出块的作用域时调用对象的
退出方法。您的
\uuuuuuuuuuuuuuuuuuuuuuuuuu
方法所做的只是打印
对象\u已删除
。实际上,您必须将用于销毁对象的代码放在
\uuuuu exit\uuuu
方法中(但请注意,这不是一个好的做法!)

发生的情况是:

with Things('socks','food',12) as stuff:
    # the __enter__() method is called and the returned object
    # is assigned to the variable "stuff"
    greg = stuff.clothes
    print(greg)
# when you've exited the block here, the __exit__() method is called.

关于显式删除对象的愿望,您应该将其留给Python的垃圾收集器。读一下这个,它会有帮助的。您可以尝试使用或重写
方法。以下是。

Python的
with
语句不是关于删除对象的,而是关于资源管理的。
\uuuuuuuuuuuuu进入
\uuuuuuu退出
方法用于提供资源初始化和销毁代码,即您可以选择删除其中的某些内容,但不会隐式删除对象。阅读一下这篇文章,更好地理解如何使用它

对象保留在
with
语句之后的范围内。如果您需要的话,可以在上面调用
del
。因为它在范围内,所以可以在关闭它的基础资源后查询它。考虑这个伪代码:

class DatabaseConnection(object):
  def __init__(self, connection):
    self.connection = connection
    self.error = None

  def __enter__(self):
    self.connection.connect()

  def __exit__(self, exc_type, exc_val, exc_tb):
    self.connection.disconnect()

  def execute(self, query):
    try
      self.connection.execute(query)
    except e:
      self.error = e

with DatabaseConnection(connection) as db:
  db.execute('SELECT * FROM DB')
if db.error:
  print(db.error)

del db
我们不希望数据库连接的挂起时间超过我们需要的时间(另一个线程/客户机可能需要它),因此我们允许释放资源(隐式地在
with
块的末尾),但之后我们可以继续查询对象。然后,我添加了一个显式的
del
,告诉运行时代码已使用变量完成

尝试正确删除Python对象

这是您的第一个错误,解释语言使您不必担心删除对象以释放内存。它们所做的是在没有更多引用且对象不再在范围内时删除它们

第二:

with Things('socks','food',12) as stuff:
    greg = stuff.clothes
    print(greg)
使用带有
,尽管缩进

将代码与以下内容进行对比:

class Things(object):
   def __init__(self, clothes, food, money):
       self.clothes = clothes
       self.food = food
       self.money = money

   def __enter__(self):
       return self

   def __exit__(self, exc_type, exc_val, exc_tb):
       print('object deleted')

stuff = "no stuff"
def do_it():
    with Things('socks','food',12) as stuff:
        greg = stuff.clothes
        print(greg)
        print(stuff)

do_it()
print(stuff)
其中:

socks
<__main__.Things object at 0xb744370c>
object deleted
no stuff
袜子
对象删除
没有东西
在这里,
do_it()
中的内部
stuff
不再存在,因此当第二个
打印(stuff)
运行时,会出现
“no stuff”


最后,不要担心删除对象。它会发生的,管理它不是你的工作。

所以,感谢大家提供的好链接。但我真的很想删除一个对象,而不是等待花哨的垃圾收集器。这起到了作用:

class Things(object):
   def __init__(self,clothes, food, money):
       self.clothes = clothes
       self.food = food
       self.money = money

   def __enter__(self):
       return self

   def __exit__(self, exc_type, exc_val, exc_tb):
       print('nothing happens')



with Things('socks','food',12) as stuff:
    print(stuff.clothes)
    del stuff


print(stuff)
现在返回:

socks
nothing happens
Traceback (most recent call last):
  File "/home/jeff/PycharmProjects/tensorflow_sandbox/main", line 36, in <module>
    print(stuff)
NameError: name 'stuff' is not defined
袜子
什么也没发生
回溯(最近一次呼叫最后一次):
文件“/home/jeff/PycharmProjects/tensorflow_sandbox/main”,第36行,中
印刷品(材料)
NameError:未定义名称“stuff”

万岁!它被删除了

嗯,它并不是100%正确的。您不能在@user3583384内删除
self
。您正在执行要删除的对象的方法。但是您的代码非常简单,是否需要使用上下文管理器?为什么不:
stuff=Things(…);格雷格=东西、衣服;印刷(格雷格);del stuff
?这就是我在回答中所说的-
with
不会删除。如果要尝试“强制”删除,您仍然必须调用
del
。您可以删除
\uuuuu exit\uuuu
中对象的字段,但该对象仍在
with
块之后的范围内。你已经在你的例子中看到了这一点。@ChuckLoganLim:你说过“[…]交给Python的垃圾收集器处理。”。实际上,在这种情况下,Python的引用计数机制将删除该对象。垃圾收集器甚至看不到它。@AlexTaylor:
del
不会删除该对象
del
将删除绑定到对象的名称,之后Python可能会删除它。Alex Taylor的答案是正确的。我想补充一点,因为Python具有自动内存管理(垃圾收集),所以您不必担心删除不再使用的对象。因此,为此目的使用上下文管理器是毫无意义的。另外,名为“stuff”的变量是由
with
语句创建的,但正如您所观察到的,它会一直存在到脚本结束。如果您有一行
del stuff
,那么名称“stuff”将变得未定义。您可能需要这样做。可能的副本可能会考虑有<代码> PistMasks<代码>,它有一个<代码> .yEngulix方法创建并返回一个<代码>文件对象和一个<代码>