【问题标题】:Python - deconstructor does not delete object instancePython - 解构器不删除对象实例
【发布时间】:2023-03-30 08:49:01
【问题描述】:

我有以下问题,我是 Python 脚本的业余用户。我创建了以下类

 roof_height = 3.5 #m
 E = 30000*(10^3) #kN/m^2

 class Brace():
     _registry = []


     def __init__(self,name,coord,b,d, h = roof_height):
          print('Brace created.')
          Brace._registry.append(self)
          self.name  = name 
          self.coord = coord              # pass tuple in the form of (x,y)
          self.b     = b                  # //x global
          self.d     = d                  # //y global
          self.h     = h

      def __del__(self):
          print('Destructor called, Brace deleted.')
          Brace._registry.remove(self)


      def properties(self):
          print("properties of " + self.name + " calculated")
          As = self.b*self.d
          Iy = self.b*(self.d**3)*(1/12)
          Iz = (self.b**3)*(self.d)*(1/12)
          self.Iy =  Iy
          self.Iz =  Iz
          self.As =  As

    def stiffness(self):
        print("stiffnesses of " + self.name + " calculated")
        Kx = 12*E*self.Iy/self.h
        Ky = 12*E*self.Iz/self.h

        self.Kx = Kx
        self.Ky = Ky

我已经创建了类的 _registry 通用属性,这样我就可以遍历对象,效果很好。我面临的问题如下: 1.当我创建一个对象时打印出来

 'Brace created'

显示,但是当我删除它时,消息

 'Destructor called, Brace deleted.'

在删除对象时不显示,_registry 列表也保持不变而不删除对象。列表的长度显然保持不变。

  1. 如何避免使用相同名称创建两次相同的实例,我的意思是如何检查重复的实例(相同的对象名称和属性值) 我是否必须为其编写代码,或者是否有可以使用的内置函数?

【问题讨论】:

  • “当我删除它时” - 你如何删除实例?你能把这段代码包含进去吗?
  • 我有点不清楚你希望remove() 做什么。您是否希望它从列表中删除self(在本例中为Brace 对象)从内存中删除该对象,或者您是否希望它只需将其从列表中删除?
  • 检查stackoverflow.com/questions/35488705/… 并考虑创建上下文管理器所需的方法。
  • @ason​​gtoruin 例如brace1 = Brace('K1',(3,2),0.5,1.5) 用于创建对象,del brace1 用于删除它。 @ResetACK 是的,我想删除该对象并将其从列表中删除。 @cdarke 谢谢会做。
  • __del__ 可能不是你想象的那样——它是由垃圾收集器调用的

标签: python python-3.x class object instance


【解决方案1】:

1: __del__() 可能由于与垃圾收集有关的多种原因而未被调用。来自documentation

注意 del x 不直接调用 x.__del__() —— 前者的减量 x 的引用计数加一,后者仅在以下情况下调用 x 的引用计数达到零。一些常见的情况可能 防止对象的引用计数变为零包括: 对象之间的循环引用(例如,双向链表或 具有父子指针的树数据结构);参考 捕获异常的函数的堆栈帧上的对象 (存储在 sys.exc_info()[2] 中的回溯保存堆栈帧 活);或对堆栈帧上引发的对象的引用 交互模式下未处理的异常(回溯存储在 sys.last_traceback 使堆栈帧保持活动状态)。第一种情况 只能通过明确打破循环来补救;第二个可以 通过释放对回溯对象的引用来解决它 不再有用,第三个可以通过存储 None 来解决 sys.last_traceback。检测到垃圾的循环引用 并在启用循环垃圾收集器时清理(它在 默认)。有关更多信息,请参阅 gc 模块的文档 有关此主题的信息。

与其依赖内置的内存管理功能,也许您可​​以实现一个定制功能,以便在不再需要某个对象时释放资源?

2:为避免两个实例同名,请使用factory pattern

【讨论】:

  • 谢谢大家的回复。你帮助我理解了循环引用和python的garbage_collector的问题。通过您的参考,我还发现了这个link,这有助于更好地理解它。现在我决定删除注册表列表并创建一个包含我想要在类之外的对象的列表。这样就没有剩下的引用了,并且在引用关闭时调用了析构函数。我
猜你喜欢
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多