Python对象删除自己
为什么这不工作? 我试图让一个类的实例删除自己。
>>> class A(): def kill(self): del self >>> a = A() >>> a.kill() >>> a <__main__.A instance at 0x01F23170>
“自我”只是对象的一个参照。 'del self'是从kill函数的本地命名空间中删除'self'引用,而不是实际的对象。
要亲自看到这个,看看这两个函数执行时会发生什么:
>>> class A(): ... def kill_a(self): ... print self ... del self ... def kill_b(self): ... del self ... print self ... >>> a = A() >>> b = A() >>> a.kill_a() <__main__.A instance at 0xb771250c> >>> b.kill_b() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 7, in kill_b UnboundLocalError: local variable 'self' referenced before assignment
你不需要使用del删除第一个地方的实例。 一旦对象的最后一个引用消失,对象将被垃圾收集。 也许你应该告诉我们更多关于完整的问题。
在这个特定的背景下,你的例子没有多大意义。
当一个生物拿起一个物品时,这个物品保留一个个体的存在。 它并没有消失,因为它被拾起。 它仍然存在,但它是(a)与存在物相同的位置,(b)不再有资格被提取。 状态发生变化时,它仍然存在。
存在与物品之间存在双向关联。 存在有一个集合中的项目。 该项目与一个存在相关联。
当一件物品被一个存在物拾起时,有两件事情必须发生。
-
存在如何在一些项目中添加项目。 例如,您的
bag
属性可以是这样的一个set
。 [list
是一个不好的select – 包里的订单是否重要?] -
物品的位置从原来的位置改变到存放的位置。 可能有两个类:物品 – 具有独立位置感的物品(因为它们自己移动)以及必须将位置委托给他们所在的存在物或地点的物品。
在任何情况下,任何Python对象都不需要被删除。 如果一件物品“被摧毁”,那么它不在存在的包里。 这不是在一个位置。
player.bag.remove(cat)
所有这一切都需要让猫从袋子里出来。 由于猫没有在其他地方使用,它将作为“已使用”的内存而存在,并且不存在,因为程序中没有任何内存可以访问它。 当一些量子事件发生并且内存引用被垃圾收集时,它将从内存中悄然消失。
另一方面,
here.add( cat ) player.bag.remove(cat)
会把猫放在当前的位置。 猫继续存在,不会与垃圾熄灭。
实际上,你不应该删除对象来做你正在做的事情。 相反,您可以更改对象的状态。 没有进入编码的例子就是你的玩家与怪物战斗并杀死怪物。 这个怪物的状态正在战斗。 怪物将获得所有战斗所需的方法。 当怪物因为生命值降到0而死亡时,怪物状态将变为死亡,angular色将自动停止攻击。 这种方法与使用标志甚至关键字非常相似。
显然,在python删除类是不需要的,因为他们将不再使用时自动垃圾收集。
我正在尝试同样的事情。 我有一个RPG战斗系统,其中我的死亡(自我)function必须杀死战斗机类的自己的对象。 但它似乎是不可能的。 也许我的class级游戏中我收集所有参与者的战斗应删除单位forms的“虚构”地图?
def Death(self): if self.stats["HP"] <= 0: print("%s wounds were too much... Dead!"%(self.player["Name"])) del self else: return True def Damage(self, enemy): todamage = self.stats["ATK"] + randint(1,6) todamage -= enemy.stats["DEF"] if todamage >=0: enemy.stats["HP"] -= todamage print("%s took %d damage from your attack!"%(enemy.player["Name"], todamage)) enemy.Death() return True else: print("Ineffective...") return True def Attack(self, enemy): tohit = self.stats["DEX"] + randint(1,6) if tohit > enemy.stats["EVA"]: print("You landed a successful attack on %s "%(enemy.player["Name"])) self.Damage(enemy) return True else: print("Miss!") return True def Action(self, enemylist): for i in range(0, len(enemylist)): print("No.%d, %r"%(i, enemylist[i])) print("It`s your turn, %s. Take action!"%(self.player["Name"])) choice = input("\n(A)ttack\n(D)efend\n(S)kill\n(I)tem\n(H)elp\n>") if choice == 'a'or choice == 'A': who = int(input("Who? ")) self.Attack(enemylist[who]) return True else: return self.Action()
我想我终于明白了! 看看这个代码:
import weakref class InsaneClass(): _alive = [] def __new__(cls): self = super().__new__(cls) InsaneClass._alive.append(self) return weakref.proxy(self) def commit_suicide(self): self._alive.remove(self) instance = InsaneClass() instance.commit_suicide() print(instance) # Raises Error: ReferenceError: weakly-referenced object no longer exists
当在__new__
方法中创build对象时,实例将被一个弱引用代理replace,并且只有一个引用保留在_alive类属性中。
什么是弱引用?
弱引用是垃圾收集器收集对象时不作为引用计数的引用。 考虑这个例子:
>>> class Test(): pass >>> a = Test() >>> b = Test() >>> c = a >>> d = weakref.proxy(b) >>> d <weakproxy at 0x10671ae58 to Test at 0x10670f4e0> # The weak reference points to the Test() object >>> del a >>> c <__main__.Test object at 0x10670f390> # c still exists >>> del b >>> d <weakproxy at 0x10671ab38 to NoneType at 0x1002050d0> # d is now only a weak-reference to None. The Test() instance was garbage-collected
所以对实例唯一的强引用存储在_alive类的属性中。 当commit_suicide()方法删除引用时,实例将被垃圾收集。
我不能告诉你这是怎么可能的类,但function可以删除自己。
def kill_self(exit_msg = 'killed'): global kill_self del kill_self return exit_msg
并看到输出:
>>> kill_self <function kill_self at 0x02A2C780> >>> kill_self() 'killed' >>> kill_self Traceback (most recent call last): File "<pyshell#28>", line 1, in <module> kill_self NameError: name 'kill_self' is not defined
我不认为在不知道名字的情况下删除一个类的一个实例是可能的。
注意:如果您为该function指定了其他名称,则其他名称仍然会引用旧名称,但一旦您尝试运行该名称就会导致错误:
>>> x = kill_self >>> kill_self() >>> kill_self NameError: name 'kill_self' is not defined >>> x <function kill_self at 0x...> >>> x() NameError: global name 'kill_self' is not defined
事实上,Python通过引用计数来进行垃圾回收。 只要对对象的最后一个引用超出范围,就会被删除。 在你的例子中:
a = A() a.kill()
我不相信variables“a”有任何方式可以隐式地设置为None。
如果您对对象使用单个引用,则该对象可以通过重置该外部引用自身来杀死自己,如下所示:
class Zero: pOne = None class One: pTwo = None def process(self): self.pTwo = Two() self.pTwo.dothing() self.pTwo.kill() # now this fails: self.pTwo.dothing() class Two: def dothing(self): print "two says: doing something" def kill(self): Zero.pOne.pTwo = None def main(): Zero.pOne = One() # just a global Zero.pOne.process() if __name__=="__main__": main()
你当然可以通过从对象外部(而不是对象状态)检查对象的存在来进行逻辑控制,例如:
if object_exists: use_existing_obj() else: obj = Obj()
我很好奇,为什么你会想要做这样的事情。 有机会,你应该让垃圾收集工作。 在python中,垃圾收集非常确定。 所以,你不必担心只是像在其他语言中留下的东西一样留在内存中(并不是说refcounting没有缺点)。
尽pipe你应该考虑的一件事是围绕你以后可能摆脱的任何对象或资源的包装。
class foo(object): def __init__(self): self.some_big_object = some_resource def killBigObject(self): del some_big_object
针对Null的附录 :
不幸的是,我不相信有办法做你想做的事情。 以下是您可能希望考虑的一种方法:
>>> class manager(object): ... def __init__(self): ... self.lookup = {} ... def addItem(self, name, item): ... self.lookup[name] = item ... item.setLookup(self.lookup) >>> class Item(object): ... def __init__(self, name): ... self.name = name ... def setLookup(self, lookup): ... self.lookup = lookup ... def deleteSelf(self): ... del self.lookup[self.name] >>> man = manager() >>> item = Item("foo") >>> man.addItem("foo", item) >>> man.lookup {'foo': <__main__.Item object at 0x81b50>} >>> item.deleteSelf() >>> man.lookup {}
这有点乱,但是这应该给你这个想法。 从本质上讲,我并不认为将游戏中的物品存在与否分配是否是一个好主意。 这是因为垃圾收集物品的条件可能与游戏中物品的条件不同。 这样,你不必担心这么多。
你可以做的是在课堂上和你一起名字,做一个词典:
class A: def __init__(self, name): self.name=name def kill(self) del dict[self.name] dict={} dict["a"]=A("a") dict["a"].kill()