0
class C():
    @property
    def x(self):
        return 0
delattr(C(), 'x')
>>> AttributeError: can't delete attribute

I'm aware del C.x works, but this deletes the class's property; can a class instance's property be deleted?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
OverLordGoldDragon
  • 1
  • 9
  • 53
  • 101
  • You can always manipulate the instance namespace dict directly. Why is `property.deleter` to "delete other attributes"? – juanpa.arrivillaga Jun 15 '20 at 09:14
  • @juanpa.arrivillaga Example? By "other attributes" I meant e.g. `self._x`, naturally not the sole purpose. – OverLordGoldDragon Jun 15 '20 at 09:16
  • `print(type(C().x))` and `print(type(getattr(C(), "x")))` – Olvin Roght Jun 15 '20 at 09:16
  • Then I don't understand what you mean. What do you mean by **delete the property**? A property *always belongs to a class*. – juanpa.arrivillaga Jun 15 '20 at 09:26
  • Does this answer your question? [How does the @property decorator work?](https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work): specifically the mention of the `@x.deleter` decorator – Energya Jun 15 '20 at 09:27
  • 1
    @Energya It doesn't explain why properties cannot be deleted from an instance, no. – OverLordGoldDragon Jun 15 '20 at 09:41
  • @juanpa.arrivillaga Have a reading reference for your statement? @ "belongs to a class", i.e. "can't remove from instance" – OverLordGoldDragon Jun 15 '20 at 09:43
  • 3
    https://stackoverflow.com/questions/1684099/is-it-possible-to-delete-a-method-from-an-object-not-class-in-python Seems like you cant delete a method from an instance, seems like you are forced to override the method on the instance – Jerome Paddick Jun 15 '20 at 09:43
  • A reference? Yes. Read the python documentation on descriptors, `property` objects are merely descriptors. It's *also what you wrote*. The `property` decorator returns a property object, which is assigned to the class namespace. It works like any other class attribute in a class definition. Look at `vars(C())` and `vars(C)` – juanpa.arrivillaga Jun 15 '20 at 09:45
  • @Mr_Nitrogen Indeed, this does explain things – OverLordGoldDragon Jun 15 '20 at 09:47
  • @juanpa.arrivillaga The property stuff isn't even relevant, it appears. – OverLordGoldDragon Jun 15 '20 at 09:52
  • No, it's relevant. But again, you never answered, *what do you mean by deleting the property*? What would be the *behavior* you want to see? – juanpa.arrivillaga Jun 15 '20 at 09:52
  • @juanpa.arrivillaga It's shown in my answer. Simply removing the attribute from the instance, as if it were defined via `self.x = 0`. So gone from `dir`, `vars`, `hasattr` etc. – OverLordGoldDragon Jun 15 '20 at 09:54
  • @OverLordGoldDragon you can't do that because it makes no sense, that's like trying to delete a method from an instance: methods to not live in instances, and neither do properties. If you want to be able to remove x from the instance, then it has to be an instance attribute. – Masklinn Jun 15 '20 at 10:54

4 Answers4

2

Refer to this answer; TL;DR, it's not about properties, but bound attributes, and x is bound to the class, not the instance, so it cannot be deleted from an instance when an instance doesn't have it in the first place. Demo:

class C():
    pass

@property
def y(self):
    return 1

c = C()
c.y = y
del c.y  # works
c.y
>>> AttributeError: 'C' object has no attribute 'y'
OverLordGoldDragon
  • 1
  • 9
  • 53
  • 101
1

I'm aware del C.x works, but this deletes the class's property; can a class instance's property be deleted?

There's no such thing. Properties are defined on the class, there is nothing on the instance in the example you provide. It's like a method, a method is an attribute of the class which Python execute in the context of the instance.

Masklinn
  • 34,759
  • 3
  • 38
  • 57
0

I got the same error below:

AttributeError: can't delete attribute

When trying to delete the instance variable name with del as shwon below:

class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

obj = Person("John")

print(hasattr(obj, "name"))

del obj.name # Here

print(hasattr(obj, "name"))

So, I added @name.deleter method as shown below:

class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

    @name.deleter # Here
    def name(self):
        del self._name

obj = Person("John")

print(hasattr(obj, "name"))

del obj.name # Here

print(hasattr(obj, "name"))

Then, I could delete the instance variable name with del as shown below:

True
False
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
-1

You can do something like this to delete attr from instance.

https://stackoverflow.com/a/36931502/12789671

class C:
    def __init__(self):
        self._x: int = 0
    @property
    def x(self):
        return self._x
    @x.deleter
    def x(self):
        delattr(self, "_x")

obj = C()
delattr(obj, "x")
try:
    print(obj.x)
except AttributeError:
    print("failed to print x")

print(C().x)
failed to print x
0