Как можно скрыть атрибуты объекта от внешнего доступа?

В Python можно скрыть атрибуты объекта, используя:

  • Соглашение об именовании: Префикс в виде одного (_attribute) или двух (__attribute) подчеркиваний. Одно подчеркивание указывает, что атрибут предназначен для внутреннего использования (protected), а два подчеркивания вызывают "name mangling" (делают атрибут более сложным для доступа извне, но не полностью недоступным).
  • Свойства (properties): Использование декораторов @property, @attribute.setter, @attribute.deleter позволяет контролировать доступ к атрибутам через методы.

Пример (name mangling):

class MyClass:
    def __init__(self):
      self.__private_attribute = 10

  obj = MyClass()
  # print(obj.__private_attribute) # AttributeError
  print(obj._MyClass__private_attribute) # Работает, но не рекомендуется

Пример (properties):

class MyClass:
    def __init__(self):
      self._my_attribute = None

    @property
    def my_attribute(self):
      return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
      # Логика валидации или преобразования значения
      self._my_attribute = value
  

В Python можно скрыть атрибуты объекта от внешнего доступа, используя несколько подходов:

  1. Соглашение об именовании:

    Наиболее распространенный способ – использовать одинарное подчеркивание (_attribute) или двойное подчеркивание (__attribute) перед именем атрибута. Это соглашение сигнализирует разработчикам, что атрибут предназначен для внутреннего использования и не должен изменяться или использоваться напрямую извне класса.

    • _attribute: Означает "protected" (защищенный). Это соглашение предполагает, что атрибут не должен использоваться вне класса и его подклассов, но Python не применяет никаких ограничений.
    • __attribute: Означает "private" (приватный). Python применяет механизм искажения имен (name mangling), чтобы сделать атрибут менее доступным извне. Имя атрибута изменяется на _ClassName__attribute, где ClassName – имя класса. Это усложняет доступ, но не делает атрибут полностью недоступным.

    Пример:

    
    class MyClass:
      def __init__(self):
        self._protected_attribute = 10
        self.__private_attribute = 20
    
      def get_private(self):
        return self.__private_attribute  # Доступ внутри класса
    
    obj = MyClass()
    print(obj._protected_attribute) # Можно получить доступ, но не рекомендуется
    # print(obj.__private_attribute) # Вызовет AttributeError
    print(obj.get_private()) # Правильный способ доступа к "приватному" атрибуту
    print(obj._MyClass__private_attribute) # Очень не рекомендуется, но возможно
          
  2. Свойства (Properties):

    Свойства предоставляют более контролируемый способ управления доступом к атрибутам. Можно использовать декораторы @property, @attribute.setter, и @attribute.deleter, чтобы определить методы для получения, установки и удаления значения атрибута. Это позволяет добавить логику валидации, преобразования или другую логику при доступе к атрибуту.

    Пример:

    
    class MyClass:
      def __init__(self):
        self._my_attribute = 0
    
      @property
      def my_attribute(self):
        return self._my_attribute
    
      @my_attribute.setter
      def my_attribute(self, value):
        if value < 0:
          raise ValueError("Значение не может быть отрицательным")
        self._my_attribute = value
    
      @my_attribute.deleter
      def my_attribute(self):
        del self._my_attribute
    
    obj = MyClass()
    print(obj.my_attribute) # Получение значения через getter
    obj.my_attribute = 5 # Установка значения через setter
    # obj.my_attribute = -1 # Вызовет ValueError
    del obj.my_attribute # Удаление атрибута через deleter
          

Важно: В Python нет абсолютной приватности в том смысле, как это реализовано в некоторых других языках. Всегда существует способ обойти механизмы сокрытия. Цель этих механизмов – поощрять хорошую практику программирования и предотвращать случайные ошибки, а не обеспечивать строгую безопасность.

0