Удалить экземпляр объекта из функции класса в python - PullRequest
1 голос
/ 06 августа 2020

Я хотел бы удалить экземпляр своего объекта после выполнения функции, чтобы ни один сценарий python больше не мог получить доступ к этому экземпляру.

Вот мой код:

class MyClass():
    def myFunc(self):
       ...
       del self

myClass = MyClass()
myClass.myFunc()
print(myClass) # Supposed to raise an error because myClass is supposed to be deleted but that's not the case

Что не так?

Ответы [ 2 ]

1 голос
/ 06 августа 2020

Вы неправильно поняли, как работает del. Он не удаляет предметы. Он удаляет имена.

Например, у вас есть

>>> x = [1, 2, 3]
>>> y = x
>>> z = x

Все три имени, x, y, z относятся к одному и тому же объекту списка. Теперь удалите x:

>>> del x
>>> x
NameError: name 'x' is not defined

Для y и z после этого не имело бы смысла поднимать NameError. Особенно представьте, если бы y и z были ссылками в другой функции или модуле. Если del x заставит другие ссылки исчезнуть, это приведет к очень неожиданному и нежелательному поведению.

Итак, при нормальных обстоятельствах вы не можете делать то, что хотите. Ваш текущий метод просто удаляет имя self в локальном пространстве имен самого метода. Он не может легко изменить глобальное пространство имен.

При этом вы можете написать функцию, которая удаляет имя из глобального пространства имен. Например:

class MyClass:
    def myFunc(self, name):
        del globals()[name]

myInst = MyClass()
myInst.myFunc('myInst')

Теперь, если вы попытаетесь получить доступ к myInst, имя исчезнет в скрипте. Это плохая идея, и, скорее всего, она все равно не удалит объект. Если у вас есть другая ссылка на myInst, например, в list, dict или прямое присвоение другому имени, эта ссылка будет сохраняться, как и сам объект.

Намного лучший подход, как предлагается в комментариях, это пометить экземпляр как непригодный для использования. Например, вы можете сделать что-то вроде

class MyClass:
    def __init__(self):
        self.useable = True

    def my_func(self):
        self._check_useable()

        # do your thing...

        self.useable = False

    def other_func(self, *args):
        self._check_useable()
        # Do stuff to args ...

    def _check_useable(self):
        if not self.useable:
            raise ValueError('Class is not useable!')

Существуют более надежные способы реализации флага, чтобы сделать его менее доступным для обычного пользователя, но они в основном следуют тому же шаблону.

0 голосов
/ 06 августа 2020

Поскольку вы не можете удалять объекты в python, а удалять только внешний вид переменных в пространстве имен. Я бы рекомендовал просто выдавать ошибку после однократного вызова функции. Поскольку вы хотите, чтобы после его запуска возникла ошибка.

class MyClass():
   def myFunc(self):
      ...
      counter += 1
      del self

counter = 0
# Check if the function has been run once and then raise exception
if counter > 0:
    raise exception("Instance cannot be used")

myClass = MyClass()
myClass.myFunc()
print(myClass)

Я надеюсь, что это по-прежнему делает то, что вы ожидаете, но функция del только удаляет внешний вид переменной в пространстве имен и не позволяет вам ссылаться на нее больше (но не удаляется).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...