使用__del__和属性方法一起的方法是什么?

4

属性包装器方法是Python中一个不错的特性,但这个问题并不是关于此特性的。我想知道是否可以在Python析构函数__del__中使用它,一个实际的例子可能是数据库连接。为简化起见,假设我们有以下类:

class Point(object):
"""docstring for Point"""

def __init__(self, x, y):
    self.x = x
    self.y = y

@property
def x(self):
    print('x getter got called')
    return self._x

@x.setter
def x(self, x):
    print('x setter got called')
    self._x = x

def __str__(self):
    return '[%s:%s]' % (self.x, self.y)

def __del__(self):
    print('destructor got called')
    del self.x
    del self.y

作为一个测试案例,我们假设有以下内容:

a = Point(4, 5)
del a

输出结果为:
Exception AttributeError: "can't delete attribute" in <bound method Point.__del__ of <__main__.Point object at 0x7f8bcc7e5e10>> ignored

如果我们删除属性部分,一切都会顺利进行。有人可以指出问题在哪里吗?

1
你想要 del self._x - salparadise
这个完美地运作,你有没有想过使用 @x.deleter 处理对象解构会更好,还是在 del 方法中处理所有对象属性的解构,第二种选项我们要写更少的代码。 - rachid el kedmiri
1
通常情况下,你应该避免使用__del__来处理这个问题,因为这很容易导致内存泄漏。相反,你应该使用上下文管理器。 - juanpa.arrivillaga
@juanpa.arrivillaga,您能否进一步阐述如何针对这个特定情况使用上下文管理器,以释放资源?非常感谢您的帮助。 - rachid el kedmiri
1
@ponach 看看这个 - juanpa.arrivillaga
2个回答

3

为你的属性x添加一个删除器,以进行清理。默认情况下,如果未为属性定义fdel,则会引发你看到的AttributeError异常:

@x.deleter
def x(self):
    print("x deleter got called")
    del self._x

这个完美地运作,你有没有想过使用 @x.deleter 处理对象解构会更好,还是在 del 方法中处理所有对象属性的解构,第二种选项我们要写更少的代码。 - rachid el kedmiri
1
@ponach 虽然我个人想不出在__del__中使用del self._x的缺点(也许有人知道,希望他们能发表意见),但让属性负责管理其所管理的属性的删除绝对是语义上更优越的。 - Dimitris Fasarakis Hilliard

2

如果您不使用@x.deleter来定义删除行为(就像您使用@x.setter一样),那么无法删除该属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接