【发布时间】:2020-04-17 20:46:46
【问题描述】:
假设有人不知道__del__ 和__delete__ 之间的区别是什么?写一个解释。
【问题讨论】:
标签: python python-3.x destructor destruction
假设有人不知道__del__ 和__delete__ 之间的区别是什么?写一个解释。
【问题讨论】:
标签: python python-3.x destructor destruction
object.__del__(self):在实例即将被销毁时调用。这也称为终结器或(不正确的)析构函数。如果基类具有
__del__()方法,则派生类的__del__()方法(如果有)必须显式调用它以确保正确删除实例的基类部分。
我认为这意味着在 my_object 的引用计数降至零后,CPython 的垃圾收集器将调用 my_object.__del__。
object.__delete__(self, instance):调用以删除所有者类的实例
instance上的属性。
__delete__ dunder 方法与 python 的descriptors 概念有关;描述符是“定义方法__get__()、__set__() 或__delete__() 的任何对象。”描述符可用于实现属性查找/分配/删除的自定义行为(分别通过__get__/__set__/__delete__)。
del statement:“删除名称会从本地或全局命名空间中删除该名称的绑定...删除属性引用、订阅和切片将传递给所涉及的主要对象...”delattr 内置函数。从文档中,“如果对象允许,该函数会删除命名属性。例如,delattr(x, 'foobar') 等效于 del x.foobar。”object.__delattr__(self, name)。根据文档,“仅当del obj.name 对对象有意义时才应实施。”因此,使用 MyClass.__delattr__ 方法定义用户类可以在例如以下情况下启用自定义行为。语句 del my_object.an_attr 被调用,或者(等效地)在调用 delattr(my_object, 'an_attr') 时。object.__delitem__(self, key) 是“调用以实现对self[key] 的删除”。因此,使用 MyClass.__delitem__ 方法定义用户类可以在例如以下情况下启用自定义行为。语句del my_object[a_key] 被调用。【讨论】:
__del__ 会在您删除对象时调用,__delete__ 有时会在您删除对象的属性时调用。
del x.my_num # __delete__
del x # __del__
__del__:
以下代码显示何时调用__del__:
class MyClass:
def __init__(self):
file = open("really_cool_file.txt", "w+")
self._f = file
def __del__(self):
print("closing any open files ")
self._f.close()
my_instance = MyClass()
del my_instance
如果my_instance是指向数据的最后一个标签,那么del my_instance调用MyClass.__del__(my_instance)
从技术上讲,del my_instance 只会删除标签 my_instance。想象一下聚会上的人都戴着名字标签。有时一个人同时有 6 或 7 个姓名标签,而其他时候,他们只有一个。 Python 会将任何未佩戴至少一个姓名标签的人踢出派对。 MyClass.__del__(my_instance) 在从一条数据中删除最后一个名称标签/标签时被调用。
上面的代码显示了我们何时确保关闭打开的文件的示例。另一个例子可能是计算给定类的活动实例数:
class Klass:
count = 0
# `count` belongs to the class
# instances do not each get their own copy of `count`
def __init__(self):
type(self).count += 1
self.instance_var = "I belong to instances"
def __del__(self):
type(self).count -= 1
obj = Klass()
print(obj.count)
__delete__
与__del__ 不同,__delete__ 与描述符有关。
下面的代码描述了obj.my_var或getattr(obj, “my_var”)的行为
克劳斯类: def getattribute(self, attrname): 尝试: 来自实例 Klaus 的属性 = attrname 除了属性错误: 属性 = 来自 Klaus 类的 attrname
# Begin code for handling "descriptors"
if hasattr(attribute, '__get__'):
attr = attribute.__get__(self, Klaus)
# End code for handling "descriptors"
return attribute
如果my_var是一个描述符,那么下面两行代码等效:
x = obj.my_var
x = Klass.my_var.__get__(obj, "my_var")
就像__getattribute__检查属性是否有__get__方法一样,__delattr__会检查属性是否有__delete__方法。
def __delattr__(self, name):
attribute = getattr(self, name)
if hasattr(attribute, "__delete__"):
attribute.__delete__(self)
else:
del self.__dict__[name]
您可以通过查看以下代码了解何时调用__delete__:
class desc:
def __delete__(descriptor, instance_of_Klaus):
print("attribute was deleted")
class Klaus:
d = desc()
def __init__(self):
pass
my_instance = Klaus()
del my_instance.d
在处理描述符时,下面这几行代码都是等价的:
del my_instance.d
delattr(my_instance, "d")
Klaus.d.__delete__(my_instance)
【讨论】:
del 在您执行 del something 时不会被调用。当对象的引用计数达到零时(或更一般地说,当引用对象被垃圾回收时)调用它。这其实是不同python实现不兼容的根源
del 不会删除对象,它会删除 names。 Python 没有明确控制对象的分配/解除分配。我认为这是一个很好的问题,这可能是一个很好的答案,但它的一个基本部分是错误的,因此具有误导性。 IOW:“del my_instance 与 MyClass.__del__(my_instance) 相同”是绝对错误的。