Почему это не сработает? Я пытаюсь удалить экземпляр класса.
>>> class A():
def kill(self):
del self
>>> a = A()
>>> a.kill()
>>> a
<__main__.A instance at 0x01F23170>
@hop: Одним из случаев может быть "контейнер" со слабыми ссылками, удаляющийся при удалении содержащихся в нем объектов.






«Я» - это всего лишь ссылка на объект. 'del self' удаляет ссылку 'self' из локального пространства имен функции kill вместо фактического объекта.
Чтобы убедиться в этом, посмотрите, что происходит, когда выполняются эти две функции:
>>> 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 для удаления экземпляров. После того, как последняя ссылка на объект исчезнет, объект будет удален сборщиком мусора. Может быть, вам стоит рассказать нам больше о полной проблеме.
Есть ли способ разработать метод, который заставит экземпляр удалить сам себя или вызвать глобальную функцию для его удаления?
@Zen в Python нет возможности удалить экземпляр. Все, что вы можете сделать, это удалить ссылки на экземпляр, и как только они все исчезнут, объект будет возвращен.
Есть ли ключ к удалению всех этих ссылок?
@Zen, вы должны достаточно хорошо понимать свою программу, чтобы знать, что относится к вашему объекту. Почему вы пытаетесь удалить объект? Почему вас это волнует, он уйдет сам по себе, когда его больше не будут использовать.
Действительно, Python выполняет сборку мусора посредством подсчета ссылок. Как только последняя ссылка на объект выпадает из области видимости, она удаляется. В вашем примере:
a = A()
a.kill()
Я не верю, что переменная 'a' может неявно установить для себя значение None.
Мне любопытно, зачем вам это нужно. Скорее всего, вам просто нужно позволить сборке мусора делать свою работу. В 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
{}
Это немного запутано, но это должно дать вам представление. По сути, я не думаю, что привязка существования элемента в игре к тому, размещен он в памяти или нет, является хорошей идеей. Это связано с тем, что условия для предмета, который будет собираться мусором, вероятно, будут отличаться от условий для предмета в игре. Таким образом, вам не нужно сильно об этом беспокоиться.
В этом конкретном контексте ваш пример не имеет большого смысла.
Когда Существо берет предмет, предмет сохраняет свое индивидуальное существование. Он не исчезает, потому что его подобрали. Он все еще существует, но он (а) находится в том же месте, что и Существо, и (б) больше не может быть поднят. Хотя у него было изменение состояния, оно все еще существует.
Между Бытием и Предметом существует двусторонняя связь. У Существа есть Предмет в коллекции. Предмет связан с Существом.
Когда Существо берет Предмет, должны произойти две вещи.
Существо как добавляет Предмет в некоторые set предметов. Ваш атрибут bag, например, может быть таким set. [list - плохой выбор - имеет ли значение порядок в сумке?]
Местоположение Предмета меняется с того, где он был раньше, на местонахождение Существа. Вероятно, существует два класса предметов - те, которые обладают независимым чувством местоположения (потому что они перемещаются сами по себе), и предметы, которые должны делегировать местоположение Существу или месту, где они находятся.
Ни при каких обстоятельствах не нужно удалять какой-либо объект Python. Если предмет «уничтожен», значит, он не в сумке Существа. Это не в месте.
player.bag.remove(cat)
Все, что нужно, чтобы выпустить кошку из мешка. Поскольку кошка больше нигде не используется, она будет существовать как "используемая" память и не существовать, потому что ничто в вашей программе не может получить к ней доступ. Он незаметно исчезнет из памяти, когда произойдет какое-то квантовое событие и ссылки на память будут собраны мусором.
С другой стороны,
here.add( cat )
player.bag.remove(cat)
Поставит кошку в текущее место. Кот продолжает существовать, и с мусором никуда не денешься.
Кот Шредингера жив! Или нет! Это надоедливое Копенгагенское толкование сбивает с толку. Итак, сборка мусора.
имеет ли это смысл ? - это религиозный вопрос, что происходит? - это научный вопрос!
@Blauohr: Поскольку я считаю, что программное обеспечение должно улавливать смысл, я делаю религиозное суждение.
@Blauohr: Поскольку я не вижу полезной разницы между тем, что имеется в виду, и тем, что происходит, если то, что происходит, не то, что означает, значит, есть ошибка, и нам нужно сделать так, чтобы происходящее соответствовало тому, что мы имели в виду. Глубокий анализ того, что происходит - когда это ошибка - бесполезен.
Я не могу сказать вам, как это возможно с классами, но функции могут удалять сами себя.
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
А теперь попробуйте это, вызвав kill_self из другого модуля.
Я пробую то же самое. У меня есть боевая система RPG, в которой моя функция Смерти (я) должна убить собственный объект класса Истребитель. Но оказалось, что это невозможно. Может быть, мой класс Game, в котором я собираю всех участников боя, должен удалять юниты с "вымышленной" карты ???
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()
Пример кода многословен, но концептуально идея «удаления с вымышленной карты» - хороший способ объяснить удаление ссылки из заданной области.
На самом деле вам не нужно удалять объект, чтобы делать то, что вы пытаетесь сделать. Вместо этого вы можете изменить состояние объекта. Примером того, как это работает, не вдаваясь в кодирование, может быть ваш игрок, сражающийся с монстром и убивающий монстра. Состояние этого монстра боевое. Монстр получит доступ ко всем методам, необходимым для боя. Когда монстр умирает из-за того, что его здоровье упадет до 0, состояние монстра изменится на мертвое, и ваш персонаж автоматически перестанет атаковать. Эта методология очень похожа на использование флагов или даже ключевых слов.
Также очевидно, что в Python удаление классов не требуется, поскольку они будут автоматически собираться мусором, когда они больше не используются.
Если вы используете одну ссылку на объект, то объект может убить себя, сбросив эту внешнюю ссылку на себя, как в:
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()
что вы могли бы сделать, так это взять это имя с собой в класс и сделать молочник:
class A:
def __init__(self, name):
self.name=name
def kill(self)
del dict[self.name]
dict = {}
dict["a"]=A("a")
dict["a"].kill()
Думаю, наконец-то я понял!
ПРИМЕЧАНИЕ: вы не должны использовать это в обычном коде, но это возможный.
Это всего лишь любопытство, посмотрите другие ответы на реальные решения этой проблемы.
# 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 class. И когда метод commit_suicide () удаляет ссылку, экземпляр собирается сборщиком мусора.
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)
Может ли этот код работать?
Добро пожаловать в Stack Overflow! Спасибо за этот фрагмент кода, который может оказать некоторую немедленную помощь. правильное объяснение значительно улучшило бы его долгосрочную ценность, показывая Почему, это хорошее решение проблемы, которое сделает его более полезным для будущих читателей с другими похожими вопросами. Пожалуйста, редактировать свой ответ, чтобы добавить некоторые пояснения, включая сделанные вами предположения.
Это то, что я делал в прошлом.
Создайте список объектов, и затем вы сможете удалить объекты сами с помощью метода list.remove().
bullet_list = []
class Bullet:
def kill_self(self):
bullet_list.remove(self)
bullet_list += [Bullet()]
Запасной орудие:
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
зачем вам вообще это нужно?