Подтвердить что ты не робот

Удаленный объект Python

Почему это не работает? Я пытаюсь сделать экземпляр класса delete.

>>> class A():
    def kill(self):
        del self


>>> a = A()
>>> a.kill()
>>> a
<__main__.A instance at 0x01F23170>
4b9b3361

Ответ 1

'self' - это только ссылка на объект. '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

Ответ 2

Вам не нужно использовать del для удаления экземпляров в первую очередь. Как только последняя ссылка на объект исчезнет, ​​объект будет собираться мусором. Может быть, вы должны рассказать нам больше о полной проблеме.

Ответ 3

В этом конкретном контексте ваш пример не имеет большого смысла.

Когда Бытие подбирает Предмет, предмет сохраняет индивидуальное существование. Он не исчезает, потому что его подбирают. Он все еще существует, но он (а) находится в том же месте, что и Существо, и (б) больше не может быть выбран. Несмотря на изменение состояния, оно все еще существует.

Существует двухсторонняя связь между Бытием и Элементом. Существо имеет Предмет в коллекции. Элемент связан с Существом.

Когда предмет подбирается Существом, должно произойти две вещи.

  • Бытие как добавляет Item в некоторые set элементов. Например, ваш атрибут bag может быть таким set. [A list - плохой выбор - имеет ли порядок вещей в сумке?]

  • Местоположение элемента изменяется с того места, где оно было, до места Бытия. Есть, вероятно, два класса os Items - те, у которых есть независимое чувство местоположения (потому что они перемещаются сами по себе) и предметы, которые должны делегировать местоположение Существо или Место, где они сидят.

Ни в коем случае ни один объект Python не должен удаляться. Если предмет "разрушен", то это не в сумке Бытия. Это не в месте.

player.bag.remove(cat)

Это все, что нужно, чтобы выпустить кошку из сумки. Поскольку кошка не используется нигде, она будет существовать как "используемая" память и не существует, потому что ничто в вашей программе не может получить к ней доступ. Он будет спокойно исчезать из памяти, когда произойдет какое-то квантовое событие, а ссылки на память - сбор мусора.

С другой стороны,

here.add( cat )
player.bag.remove(cat)

Поместите кошку в текущее местоположение. Кошка продолжает существовать и не будет потушена с мусором.

Ответ 4

Я думаю, что наконец-то понял!
ПРИМЕЧАНИЕ. Не следует использовать это в обычном коде, но это возможно. Это только для любопытства, см. Другие ответы для реальных решений этой проблемы.


Посмотрите на этот код:
# 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() удаляет ссылку, экземпляр собирается сборщиком мусора.

Ответ 5

Реально, вам не нужно удалять объект, чтобы делать то, что вы пытаетесь сделать. Вместо этого вы можете изменить состояние объекта. Пример того, как это работает, не попадая в кодировку, будет вашим игроком, сражающимся с монстром и убивающим монстра. Состояние этого монстра борется. У монстра будут доступ ко всем методам, необходимым для борьбы. Когда монстр умирает, потому что его здоровье падает до 0, состояние монстров изменится на мертвое, и ваш персонаж автоматически прекратит атаку. Эта методология очень похожа на использование флагов или даже ключевых слов.

Также очевидно, что в классах удаления python не требуется, так как они будут автоматически собираться с мусором, если они больше не используются.

Ответ 6

Я не могу рассказать вам, как это возможно с классами, но функции могут удалять сами.

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

Ответ 7

Я пытаюсь сделать то же самое. У меня есть боевая система 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()

Ответ 8

Действительно, Python делает сборку мусора через подсчет ссылок. Как только последняя ссылка на объект выпадает из области действия, она удаляется. В вашем примере:

a = A()
a.kill()

Я не верю, что для переменной 'a' не было никакого значения, чтобы она не указывала на None.

Ответ 9

Если вы используете единственную ссылку на объект, тогда объект может убить себя, сбросив эту внешнюю ссылку на себя, как в:

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()

Ответ 10

Мне любопытно, почему вы хотели бы сделать такое. Скорее всего, вы должны просто позволить сборку мусора выполнять свою работу. В python сбор мусора довольно детерминирован. Поэтому вам не нужно беспокоиться о том, чтобы просто оставить объекты, лежащие в памяти, как на других языках (не говоря уже о том, что перерасчет не имеет недостатков).

Хотя одна вещь, которую вы должны рассмотреть, - обертка вокруг любых объектов или ресурсов, от которых вы можете избавиться позже.

class foo(object):
    def __init__(self):
        self.some_big_object = some_resource

    def killBigObject(self):
        del some_big_object

В ответ на Null addendum:

К сожалению, я не считаю, что есть способ сделать то, что вы хотите сделать так, как хотите. Здесь один из способов, который вы, возможно, пожелаете рассмотреть:

>>> 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
 {}

Это немного беспорядочно, но это должно дать вам эту идею. По сути, я не думаю, что привязка существования элемента в игре к тому, является ли она выделенной в памяти хорошей идеей. Это связано с тем, что условия для сбора мусора, вероятно, будут отличаться от условий для предмета в игре. Таким образом, вам не нужно так беспокоиться об этом.

Ответ 11

что вы могли бы сделать, это взять имя с вами в классе и сделать dictionairy:

class A:
  def __init__(self, name):
    self.name=name
  def kill(self)
    del dict[self.name]

dict={}
dict["a"]=A("a")
dict["a"].kill()

Ответ 12

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)

Может ли этот код работать?

Ответ 13

Это то, что я сделал в прошлом. Создайте список объектов, и затем вы сможете удалить объекты сами с помощью list.remove().

bullet_list = []

class Bullet:
    def kill_self(self):
        bullet_list.remove(self)

bullet_list += [Bullet()]