Skip to content

@private

A method marked @private is callable only from within the defining class. Subclasses cannot reach it. External code cannot reach it.

from strictaccess import strict_access_control, private, PrivateAccessError

@strict_access_control()
class Vault:
    @private
    def _unlock(self) -> str:
        return "secret"

    def reveal(self) -> str:
        return self._unlock()        # OK: same class
Vault().reveal()                     # "secret"
Vault()._unlock()                    # raises PrivateAccessError

Subclasses cannot reach it

class Heir(Vault):
    def try_unlock(self) -> str:
        return self._unlock()        # blocked

Heir().try_unlock()                  # raises PrivateAccessError

This matches Java's private semantics, not Python's underscore convention (where subclass access is technically allowed and just discouraged).

Use it for

  • Helpers whose contract is unstable and may change between releases.
  • Invariants you must protect — anything that, if called from outside the class, would leave the instance in an inconsistent state.
  • Methods that bypass validation done by the public API.

Avoid for

  • Methods you intend subclasses to override or extend. Use @protected for those.
  • Anything you want test code to call directly. Tests should drive the public API.

Name-mangled attributes (__x) also become private

Python's name mangling converts self.__x inside class Foo to self._Foo__x. strictaccess recognises this pattern and treats it as private:

@strict_access_control()
class Box:
    def __init__(self) -> None:
        self.__token = "k"           # stored as _Box__token

Box()._Box__token                    # raises PrivateAccessError

Combining with @classmethod / @staticmethod

Stack @private on top:

@strict_access_control()
class Foo:
    @private
    @classmethod
    def _build(cls): ...

The same internal-only rule applies. The class is identified by its qualname on the method, not by the instance.