Сообщить об ошибке.

Закрытые/приватные методы и переменные в классе Python

В языке Python не существуют закрытых переменных или методов экземпляра класса, к которым нельзя получить доступ, кроме как изнутри объекта, НО существует соглашение, которому следует большая часть кода Python.

Имя, которое определено в классе с префиксом подчеркивания, например _spam, следует рассматривать как непубличную часть API, будь то метод или атрибут данных. Это соглашение следует считать деталями реализации и оно может быть изменено без предварительного уведомления.

Существует допустимый вариант использования закрытых членов класса. Чтобы избежать конфликта имен, определенных в классе с именами, определенными в подклассах, существует ограниченная поддержка такого механизма, как искажением имен. Любой идентификатор вида __spam (не менее двух начальных подчеркиваний и не более одного конечного подчеркивания) текстуально заменяется на _classname__spam, где classname - это текущее имя класса с начальным подчеркиванием. Это искажение выполняется без учета синтаксической позиции идентификатора, если оно происходит в пределах определения класса.

Искажение имен полезно для того, чтобы позволить подклассам переопределять методы, не нарушая вызовов методов, расположенных внутри класса.

Например:

class Mapping:
    def __init__(self, iterable):
        self.items_list = []
        self.__update(iterable)

    def update(self, iterable):
        for item in iterable:
            self.items_list.append(item)

    # закрытая копия оригинального метода update()
    __update = update

class MappingSubclass(Mapping):

    def update(self, keys, values):
        # предоставляет новую сигнатуру для update()
        # но не ломается __init__()
        for item in zip(keys, values):
            self.items_list.append(item)

Приведенный выше пример будет работать, даже если в подкласс MappingSubclass будет введен идентификатор __update, так как он заменяется на _Mapping__update в классе Mapping и _MappingSubclass__update в классе MappingSubclass соответственно.

Обратите внимание, что правила искажения разработаны главным образом, чтобы избежать переназначений закрытых переменных. К закрытой переменной все еще возможно получить доступ или изменить ее. Это может быть даже полезно в особых случаях, таких как отладка кода.

Обратите внимание, что код, переданный в функции exec() или eval(), не рассматривает имя вызывающего класса - текущим классом. Это похоже на эффект оператора global , эффект которого также ограничен кодом, который байтово скомпилирован вместе. То же ограничение применяется к getattr(), setattr() и delattr(), а также при прямой ссылке на __dict__.