为什么不起作用?我试图使一个类的实例本身删除。
>>> class A():
def kill(self):
del self
>>> a = A()
>>> a.kill()
>>> a
<__main__.A instance at 0x01F23170>
为什么不起作用?我试图使一个类的实例本身删除。
>>> class A():
def kill(self):
del self
>>> a = A()
>>> a.kill()
>>> a
<__main__.A instance at 0x01F23170>
Answers:
“自我”只是对对象的引用。“ 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来删除实例。一旦对对象的最后引用消失,该对象将被垃圾回收。也许您应该告诉我们更多有关完整问题的信息。
我想我终于明白了!
注意:您不应该在常规代码中使用此功能,但是有可能。这只是出于好奇,请参阅其他答案以实际解决此问题。
# NOTE: This is Python 3 code, it should work with python 2, but I haven't tested it.
import weakref
class InsaneClass(object):
_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__
方法中创建对象时,实例将由弱引用代理替换,并且唯一的强引用将保留在_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()方法删除引用时,该实例将被垃圾回收。
在这种特定情况下,您的示例没有多大意义。
当众生拿起一个物品时,该物品会保留一个个体的存在。它不会消失,因为它已被捡起。它仍然存在,但(a)与存在者的位置相同,并且(b)不再有资格被拾取。状态更改后,它仍然存在。
存在与项目之间存在双向关联。存在在集合中有物品。该物品与存在相关联。
当一个物品被一个存在物拾取时,必须发生两件事。
存在方式将项目添加到某些set
项目中。bag
例如,您的属性可以是这样的set
。[Alist
是一个糟糕的选择-袋子里的订单重要吗?]
物品的位置从原来的位置更改为存在的位置。大概有两类os物品-具有独立位置感的物品(因为它们自己移动)和必须将位置委托给他们所坐的存在或位置的物品。
在任何情况下,都无需删除任何Python对象。如果一件物品被“摧毁”,那么它就不在人的包里。它不在某个位置。
player.bag.remove(cat)
仅是让猫从书包中脱出所需要的。由于猫没有在其他任何地方使用,因此它们都将作为“已用”内存存在,并且不存在,因为程序中没有任何内容可以访问它。当发生一些量子事件并且内存引用被垃圾回收时,它将从内存中悄悄消失。
另一方面,
here.add( cat )
player.bag.remove(cat)
将猫放到当前位置。猫继续存在,不会与垃圾一起扔掉。
实际上,您无需删除对象即可执行您想做的事情。相反,您可以更改对象的状态。在不进行编码的情况下如何工作的一个示例是您的玩家与怪物战斗并杀死怪物。这个怪物的状态正在战斗。怪物将使用战斗所需的所有方法。当怪物由于生命值降至0而死亡时,怪物状态将变为死亡,并且您的角色将自动停止攻击。这种方法非常类似于使用标志甚至关键字。
同样显然在python中,不需要删除类,因为当不再使用它们时,它们将被自动垃圾收集。
我无法告诉您类如何实现,但是函数可以删除自身。
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
我认为在不知道类名的情况下删除类的单个实例是不可能的。
注意: 如果您给该函数分配了另一个名称,该另一个名称仍将引用旧名称,但是一旦您尝试运行它,就会导致错误:
>>> 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
我正在尝试同样的事情。我有一个RPG战斗系统,其中我的Death(self)函数必须杀死Fighter类自己的对象。但是看来这是不可能的。也许我收集所有参加战斗的班级游戏应该从“虚构”地图中删除单位???
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()
如果您使用对对象的单个引用,则该对象可以通过重置对自身的外部引用来杀死自己,如下所示:
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中,垃圾回收是确定性的。因此,您实际上不必像在其他语言中那样担心仅将对象放在内存中(不必说重新计数没有缺点)。
尽管您应该考虑的一件事是包装所有对象或资源,但以后可能会抛弃它们。
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, function):
self.function = function
def kill(self):
self.function(self)
def delete(object): #We are no longer in A object
del object
a = A(delete)
print(a)
a.kill()
print(a)
此代码可以工作吗?
替换工具:
class A:
def __init__(self):
self.a = 123
def kill(self):
from itertools import chain
for attr_name in chain(dir(self.__class__), dir(self)):
if attr_name.startswith('__'):
continue
attr = getattr(self, attr_name)
if callable(attr):
setattr(self, attr_name, lambda *args, **kwargs: print('NoneType'))
else:
setattr(self, attr_name, None)
a.__str__ = lambda: ''
a.__repr__ = lambda: ''
a = A()
print(a.a)
a.kill()
print(a.a)
a.kill()
a = A()
print(a.a)
将输出:
123
None
NoneType
123