pythonpython-typingmypyruff

Access to protected class attributes from object methods


I'm learning OOP in python and ran into a problem. How to correctly access protected class attributes from object methods? Example code:

from typing import ClassVar


class Example:
    _foo: ClassVar[int] = 2
    def bar(self) -> int:
       return self._foo

    def baz(self, num: int) -> None:
        self._foo = num

if __name__ == "__main__":
    example1 = Example()
    example2 = Example()
    example1.baz(1)
    print(example1.bar())

But mypy says:

error: Cannot assign to class variable "_foo" via instance  [misc]

Ok, let's try this: self.__class__._foo. And misses again! Now ruff is swearing:

SLF001 Private member accessed: `_foo`
   |
 9 |     def baz(self, num: int) -> None:
10 |         self.__class__._foo = num
   |         ^^^^^^^^^^^^^^^^^^^ SLF001
11 |
12 | if __name__ == "__main__":
   |

So what's the right way?


Solution

  • To summarize you have a ClassVar and a protected value. ClassVars should be only set on the class object or within classmethods. Protected values should also only be accessed within the class, the clean solution is to use a classmethod to set the ClassVar:

    class Example:
        _foo: ClassVar[int] = 2
        def bar(self) -> int:
           return self._foo  # will return self.__class__._foo is not found on instance.
    
        def baz(self, num: int) -> None:
            self.class_set_foo(num)
    
        @classmethod
        def class_set_foo(cls, value):
            # Choose one, depending on wanted subclass behavior:
            cls._foo = value  # wrt. to current (sub)class, but not parent/sibling classes
            # OR
            Example._foo = value  # for all subclasses