Python的析构函数中存在分段错误



我已经创建了一个类来表示我的led条形图,我想在停止条形图时关闭它(也就是说,当程序停止并且对象被破坏时(。因此,正如我在C++中所做的那样,我创建了一个析构函数来实现这一点。但看起来Python在销毁对象后才调用它。然后我得到了一个分割错误
这是我的类,析构函数只需调用函数即可将每个LED的颜色设置为0。

class LedStrip:
def __init__(self, led_count, led_pin, led_freq_hz, led_dma, led_invert, led_brightness, led_channel, color = MyColor(0,0,0)):
self.__strip = Adafruit_NeoPixel(led_count, led_pin, led_freq_hz, led_dma, led_invert, led_brightness, led_channel)
self.__color = color
self.__strip.begin()
def __del__(self):
self.__color = MyColor(0,0,0)
self.colorWipe(10)
# ATTRIBUTS (getter/setter)
@property
def color(self):
return self.__color
@color.setter
def color(self, color):
if isinstance(color, MyColor):
self.__color = color
else:
self.__color = MyColor(0,0,0)
def __len__(self):
return self.__strip.numPixels()
# METHODS
def colorWipe(self, wait_ms=50):
"""Wipe color across display a pixel at a time."""
color = self.__color.toNum()
for i in range(self.__strip.numPixels()):
self.__strip.setPixelColor(i, color)
self.__strip.show()
time.sleep(wait_ms/1000.0)

MyColor只是我为表示RGB颜色而创建的一个类。在Python中实现该任务的正确方法是什么?我来自C++,因此我的OOP方法实际上是面向C++的,所以我在用Python的方式思考时遇到了一些困难。

提前感谢

在编写__del__方法(终结器(时,必须非常小心。它们几乎可以在对象不再被引用后的任何时候被调用(这不一定会立即发生(,而且不能保证它们会在解释器退出时被调用。如果它们在解释器退出期间被调用,那么其他对象(如全局变量和其他模块(可能已经被清理,因此对终结器不可用。它们的存在使得对象可以清理状态(如低级文件句柄、连接等(,并且不像C++析构函数那样工作。根据我的Python经验,您很少需要编写自己的__del__方法。

你可以在这里使用其他机制。一种选择是try/finally:

leds = LedStrip(...)
try:
# application logic to interact with the LEDs
finally:
leds.clear() # or whatever logic you need to clear the LEDs to zero

这仍然相当明确。如果您想要更隐式的东西,可以考虑使用Python上下文管理器结构。要使用上下文管理器,请使用with关键字:

with open("file.txt", "w") as outfile:
outfile.write("Hello!n")

CCD_ 6语句调用特殊的CCD_;上下文";。当块结束时,__exit__方法将被调用以结束"块";上下文";。对于文件,__exit__将关闭该文件。关键是即使块内部发生异常(有点像try块上的finally(,也会调用__exit__

你可以在你的LED条上实现__enter____exit__,然后写:

with LedStrip(...) as leds:
# do whatever you want with the leds

并且当块结束时,__exit__方法可以重置所有LED的状态。

让我们这样说吧。首先。。。就像我在C++中所做的那样";这种方法是不合适的,我相信你们自己也知道。不用说,Python是一种完全不同的语言。但在这种特殊情况下,应该强调这一点,因为Python的内存管理与C++截然不同。Python使用引用计数,当对象引用计数为零时,其内存将被释放(即当对象被垃圾收集时(,依此类推

Python用户定义的对象有时确实需要定义__del__()方法。但它在任何意义上都不是析构函数(当然不是C++意义上的析构函数(,它是终结器。此外,当解释器退出时,不能保证为仍然存在的对象调用__del__()方法。然而,我们可以显式调用__del__(),这不应该适用于您的情况,因此我建议将LED关闭作为一种显式方法,而不是依赖于Python的内部。就像Python的Zen(import this命令(中一样。

显式优于隐式。

有关__del__()的更多信息,请查看此正确答案。有关引用计数的更多信息,请查看本文。

最新更新