Attributes
Overview
privates.py will look for the __private__
, __protected__
, __readonly__
attributes on a supported type (more on that in a moment). Each of these must be any iterable of strings, but in these examples it will be done with a tuple
.
A supported type is something that privates.py has hooked on to. This is done automatically by the private
and class_modifier
decorators, but if you don't want to limit instantiation of your class, then you may support access-modified attributes with the supports_private
decorator:
Private
Private attributes may be accessed in methods of the class only. You generally don't want to set the __private__
attribute manually, but instead just prefix your attribute with _
:
from privates import supports_private
@supports_private
class Foo:
def __init__(self) -> None:
self._bar = "hello world"
def print_bar(self) -> None:
print(self._bar)
foo = Foo()
foo._bar # AccessError
Protected
Protected attributes may be accessed in methods of the class, and by methods of any classes that inherit from it. You must explicitly define the __protected__
attribute for these. Note that you do not need to use the @supports_private
decorator on the child class:
from privates import supports_private
@supports_private
class Foo:
__protected__ = "bar",
def __init__(self) -> None:
self.bar = "hello world"
def print_bar(self) -> None:
print(self.bar)
class Bar(Foo):
def __init__(self) -> None:
super().__init__()
self.bar = "hello, world!"
bar = Bar()
bar.print_bar()
Read Only
Read only attributes may accessed anywhere, but only written to by methods of the class (or by any classes that inherit from it). Once again, __readonly__
must be defined:
from privates import supports_private
@supports_private
class Foo:
__readonly__ = "bar",
def __init__(self) -> None:
self.bar = "hello world"
foo = Foo()
print(foo.bar)
foo.bar = "hello, world!" # AccessError
Friends
Similar to how friends work with private
, class_modifier
, and function_modifier
, you may give a function or type private access with the friend
decorator:
from privates import supports_private
@supports_private
class Foo:
def __init__(self) -> None:
self._bar = "hello world"
@friend(Foo)
def use_foo():
foo = Foo()
print(foo._bar)
use_foo()
You might be wondering, "don't you have to be more than friends to touch privates?" Hey, I don't make the rules, I only follow them!