【问题标题】:What is the difference between `__del__` and `__delete__`?`__del__` 和 `__delete__` 有什么区别?
【发布时间】:2020-04-17 20:46:46
【问题描述】:

假设有人不知道__del____delete__ 之间的区别是什么?写一个解释。

【问题讨论】:

    标签: python python-3.x destructor destruction


    【解决方案1】:

    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__)。

    另见:

    • The 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] 被调用。

    【讨论】:

      【解决方案2】:

      __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_vargetattr(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_instanceMyClass.__del__(my_instance) 相同”是绝对错误的。
      猜你喜欢
      • 2010-10-02
      • 2011-12-12
      • 2010-09-16
      • 2012-03-14
      • 2012-02-06
      • 2011-02-25
      • 2011-11-22
      • 2015-03-26
      • 2013-08-19
      相关资源
      最近更新 更多