Deleting existing class variable yield AttributeError

It seems like python register the x variable as a paramameter of the A class:

capture

Then, when you try to delete it from the B class, there is some conflict with the delattr method, like mentionned in the link that @David Herring provided...

A workaround could be deleting the parameter from the A class explicitly:

delattr(A, "x")

As you concluded in your simplified version, what goes on is simple: the attribute "x" is not in the class, it is in the superclasses, and normal Python attribute lookup will fetch it from there for reading - and on writting, that is, setting a new cls.x will create a local x in he subclass:

In [310]: class B(A): 
     ...:     pass 
     ...:                                                                                                                         

In [311]: B.x                                                                                                                     
Out[311]: 1

In [312]: del B.x                                                                                                                 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-312-13d95ac593bf> in <module>
----> 1 del B.x

AttributeError: x

In [313]: B.x = 2                                                                                                                 

In [314]: B.__dict__["x"]                                                                                                         
Out[314]: 2

In [315]: B.x                                                                                                                     
Out[315]: 2

In [316]: del B.x                                                                                                                 

In [317]: B.x                                                                                                                     
Out[317]: 1

If you need to suppress atributes in inherited classes, it is possible, though, through a custom __getattribute__ method (not __getattr__) in the metaclass. There is even no need for other methods on the metaclass (though you can use them, for, for example, editing a list of attributes to suppress)

class MBase(type):
    _suppress = set()

    def __getattribute__(cls, attr_name):
        val = super().__getattribute__(attr_name)
        # Avoid some patologic re-entrancies
        if attr_name.startswith("_"):
            return val
        if attr_name in cls._suppress:
            raise AttributeError()

        return val


class A(metaclass=MBase):
    x = 1

class B(A):
    _suppress = {"x",}

If one tries to get B.x it will raise.

With this startegy, adding __delattr__ and __setattr__ methods to the metaclass enables one to del attributes that are defined in the superclasses just on the subclass:

class MBase(type):
    _suppress = set()

    def __getattribute__(cls, attr_name):
        val = super().__getattribute__(attr_name)
        # Avoid some patologic re-entrancies
        if attr_name.startswith("_"):
            return val
        if attr_name in cls._suppress:
            raise AttributeError()

        return val

    def __delattr__(cls, attr_name):
        # copy metaclass _suppress list to class:
        cls._suppress = set(cls._suppress)
        cls._suppress.add(attr_name)
        try:
            super().__delattr__(attr_name)
        except AttributeError:
            pass

    def __setattr__(cls, attr_name, value):
        super().__setattr__(attr_name, value)
        if not attr_name.startswith("_"):
            cls._suppress -= {attr_name,}



class A(metaclass=MBase):
    x = 1

class B(A):
    pass

And on the console:

In [400]: B.x                                                                                                                     
Out[400]: 1

In [401]: del B.x                                                                                                                 

In [402]: B.x                                                                                                                     
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
... 

In [403]: A.x                                                                                                                     
Out[403]: 1