删除列表中的最后一个对象后,它不会被删除。什么时候有效删除?

pla*_*ane 2 python garbage-collection

下面的代码应该删除每个nHuman 对象,然后打印最后一行,但它只删除了其中的 4 个,在执行停止后第 5 个被删除(我认为)。

class Human():
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f'{self.name} is dead')


n = 5
humans = []
for i in range(n):
    human = Human('Bob')
    humans.append(human)

for i in reversed(range(n)):
    del humans[i]

print('DEATH')
Run Code Online (Sandbox Code Playgroud)

输出如下(Powershell 和 Python 3.8.1):

Bob is dead  
Bob is dead  
Bob is dead  
Bob is dead  
DEATH  
Bob is dead
Run Code Online (Sandbox Code Playgroud)

在第二个 for 循环humans为空之后,因此不可能通过 删除最后一个项目del humans[0]。删除列表内容 (del humans[:]humans.clear) 的其他方法也不能解决问题,输出保持不变。

那么,这是代码的行为方式还是存在一些问题?

Sam*_*ord 8

其中一个对象没有被垃圾收集,因为仍然有对它的引用:

class Human():
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f'{self.name} is dead')


n = 5
humans = []
for i in range(n):
    human = Human(f'Bob {i}')
    humans.append(human)

for i in reversed(range(n)):
    print(f'Die, {humans[i].name}!')
    del humans[i]

print('DEATH')
print(f"(except for {human.name} whom we haven't forgotten about!)")
Run Code Online (Sandbox Code Playgroud)

如果你想避免那个悬空引用,一个简单的解决方法是不要首先创建它:

n = 5
humans = []
for i in range(n):
    humans.append(Human(f'Bob {i}'))
Run Code Online (Sandbox Code Playgroud)

或者更好:

n = 5
humans = [Human(f'Bob {i}') for i in range(n)]
Run Code Online (Sandbox Code Playgroud)