How to not accidentally ovewrite a class attribute in a Child

Viewed 38
from abc import abstractmethod

class Parent:
    """ Class from some library"""
    def __init__(self):
        # how can I tell the IDE that the child class should not overwrite this?
        self.data = "don't touch this, some other method needs it"

    @abstractmethod
    def method(self):
        pass

    def some_other_method(self):
        print(self.data)


class Child(Parent):
    """ My specified class, that implements the abstract method"""
    def __init__(self, data):
        super().__init__()
        # I did not look into all parents of all parents,
        # How to know that this is dangerous?
        self.data = data

    def method(self):
        print(self.data)

child = Child('hello')
child.method()
child.some_other_method()

Is there a way to mark the data attribute in the Parent class so that pylint (or a modern IDE) would warn about overwriting the attribute in the Child? Or do I always have to check all attributes of all parents manually when using attributes in a child?

The only idea I have is checking for each attribute if it exists after initializing the parent before setting it in a child, but that also seems like some weird overhead to me.

assert not hasattr(super(), "data")


edit: To better explain what I mean, I am probably looking for something similar like the abstractmethod decorator for methods but for protected attributes instead.

For example, if I write something like this in my IDE:

class Parent:
    """ Class from some library"""
    @abstractmethod
    def method(self):
        pass


class Child(Parent):
    """ My specified class, that should implement the abstract method"""
    def __init__(self):
        super().__init__()

My IDE complains about the missing implementation of method in the Child:

Class Child must implement all abstract methods

It would be cool to have something similar to mark attributes as protected like:

class Parent:
    """ Class from some library"""
    def __init__(self):
        @protected  # does not exist I am afraid
        self.data = 'do not touch this'


class Child(Parent):
    """ My specified class, that touches the data"""
    def __init__(self):
        super().__init__()
        self.data = 'I touch it!'  # should be marked with warning

For the linter/IDE to mark the overwritten protected attribute

1 Answers

Not really, but what you can do is to prefix your attribute with __ and will automatically will be rename when you're outside of the class. See code bellow

>>> class P :
    def __init__():
        self.__data = "no overwritable"

>>> class C(P):
    def __init__(self):
        super().__init__()
        self.__data = "overwrited"

>>> c = C()
>>> c.__dict__
{'_P__data': 'no overwritable', '_C__data': 'overwrited'}

here your instance of C will have to data attribute, the one from the parent class P accessible through _P__data and the one from the child class C accessible through _C__data

In this way you don't always have to check if an attribute exists in a parent, but you can still access it if you really need it

Related