您是否更喜欢使用del或重新分配给None(垃圾收集)

时间:2011-07-14 13:31:51

标签: python

请考虑以下代码:

if value and self.fps_display is None:
    self.fps_display = clock.ClockDisplay()
elif not value and self.fps_display is not None:
    self.fps_display.unschedule()
    # Do this
    del self.fps_display
    # or this
    self.fps_display = None
    # or leave both in ?

哪个更好的python清理?

3 个答案:

答案 0 :(得分:27)

垃圾收集没有区别 - 在这两种情况下都会释放self.fps_display指向的对象引用。您应该使用哪一个取决于您是否希望名称仍然存在(尽管现在指向不同的对象,None),或者不是。

答案 1 :(得分:16)

您有一个具有属性fps_display

的对象

你不应该使该属性奇怪地可选或有时会丢失。

如果它是一流的属性 - 并且相当可见 - 必须将其设置为None以释放任何资源。删除该属性令人毛骨悚然,因为该对象现在具有可选属性并引发了惊人的异常。

self.fps_display = None

答案 2 :(得分:2)

区别在于self.fps_display = None将释放它所引用的任何内容,但是保留名称,即使它只是引用None(这是类型,NoneType)。

另一方面,del self.fps_display将完全删除名称及其引用的内容。如果此后尝试使用self.fps_display,则将引发AttributeError(如果是普通变量,则抛出NameError)。

因此,在实践中,通过为名称分配无,您仍然可以在表达式中使用该名称,而使用del时,该名称将被完全删除。在第一种情况下,需要几个字节将名称保留在内存中,而在后一种情况下,则完全清除所有内存使用情况。

一些代码来说明:

import sys
import gc

x = 'Some text here to give the variable a decent size'
y = 2
print('x value before deletion: {}'.format(x))
print('x size before deletion: {} bytes'.format(sys.getsizeof(x)))
print('y value before deletion: {}'.format(y))

x = None
del y
gc.collect() # Not really needed, just to show garbage collection has been done hereafter

print('x value after deletion: {}'.format(x))
print('x size after deletion: {} bytes'.format(sys.getsizeof(x))) # A few bytes needed to keep symbol name
print('x type after deletion: {}'.format(type(x)))

if not x:
    print('Can still use x!')

print('y value after deletion: {}'.format(y)) # Will throw NameError (AttributeError in case of class property)

输出:

x value before deletion: Some text here to give the variable a decent size
x size before deletion: 98 bytes
y value before deletion: 2
x value after deletion: None
x size after deletion: 16 bytes
x type after deletion: <class 'NoneType'>
Can still use x!
Traceback (most recent call last):
  File "Untitled.py", line 21, in <module>
    print('y value after deletion: {}'.format(y)) # Will throw NameError (AttributeError in case of class property)
NameError: name 'y' is not defined

Credits