首页 > 解决方案 > 调用 __del__ 函数时如何从列表中删除我的类对象?

问题描述

我正在尝试再次学习所有 python 基础知识,但我无法理解该__del__函数的某些内容。当我删除一个调用该__del__函数的对象时,我想在我的类列表中删除该对象。

这是我的代码,我尝试了不同的方法,但我认为我不太了解它是如何工作的。

class Player():
    players = []

    def __init__(self, pseudo):
        self.pseudo = pseudo
        self.score = 0
        self.players.append(self)

    def __str__(self):
        return ('Pseudo : {} , Score : {}'.format(self.pseudo, self.score))

    def __del__(self):
        ##How can I remove the player from my player's list ? 
        Player.players.remove(self)
        print("Player has been removed.")

标签: python

解决方案


而不是管理您的玩家列表并删除其中实例的引用,您应该使用weakrefhttps ://docs.python.org/3/library/weakref.html

对对象的弱引用不足以使对象保持活动状态:当对所指对象的唯一剩余引用是弱引用时,垃圾收集可以自由地销毁所指对象并将其内存用于其他用途。然而,在对象被实际销毁之前,即使没有强引用,弱引用也可能会返回该对象。

Player.players是 Player 实例的列表。如果您删除该对象,该列表将使该实例保持活动状态。这个列表应该只包含weakref。这将允许您访问该类的所有实例,而不会阻止删除此实例:

class Player():
    players = []

    def __init__(self, pseudo):
        ...
        self.players.append(weakref.ref(self))

为了访问被弱引用引用的对象,你只需要调用弱引用:

import weakref


class Player:
    __players = []

    def __init__(self, pseudo):
        self.pseudo = pseudo
        self.score = 0
        self.__players.append(weakref.ref(self))

    @classmethod
    def players(cls):
        for player_ref in cls.__players:
            yield player_ref()

    @classmethod
    def clean_players(cls):
        for player_ref in cls.__players:
            if player_ref() is None:
                cls.__players.remove(player_ref)

    def __str__(self):
        return ('Pseudo : {} , Score : {}'.format(self.pseudo, self.score))

    def __repr__(self):
        return f'Player object: "{self.__str__()}"'


if __name__ == '__main__':
    marvin = Player("Marvin")
    jack = Player("Jack")
    print(list(Player.players()))
    # [Player object: "Pseudo : Marvin , Score : 0", Player object: "Pseudo : Jack , Score : 0"]
    del jack
    print(list(Player.players()))
    # [Player object: "Pseudo : Marvin , Score : 0", None]
    Player.clean_players()
    print(list(Player.players()))
    # [Player object: "Pseudo : Marvin , Score : 0"]

推荐阅读