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?
To summarize you have a ClassVar
and a protected
value. ClassVar
s should be only set on the class object or within classmethod
s. 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