Инкапсуляция

Инкапсуляция — это механизм, который объединяет данные и методы, работающие с этими данными, в единый блок, скрывая внутреннюю реализацию объекта и предоставляя доступ только к необходимым частям. В Python инкапсуляция реализуется с помощью модификаторов доступа (publicprotectedprivate) и управления видимостью атрибутов и методов.

Зачем нужна инкапсуляция?

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

Модификаторы доступа в Python

В Python нет строгих модификаторов доступа, как в других языках, таких как Java или C++. Однако существуют соглашения об именовании, которые помогают достичь той же цели:

  • Public: Любой атрибут или метод без специального префикса считается общедоступным. Его можно свободно использовать вне класса.
  • Protected: Атрибуты и методы, имена которых начинаются с одного символа подчеркивания (_), считаются защищенными. Их рекомендуется использовать только внутри класса и его потомков.
  • Private: Атрибуты и методы, имена которых начинаются с двух символов подчеркивания (__), считаются приватными. Доступ к ним возможен только внутри самого класса.

Пример инкапсуляции в Python

class BankAccount:
    def __init__(self, balance=0):
        self._balance = balance  # Защищенное поле
    
    @property
    def balance(self):
        return self._balance
    
    @balance.setter
    def balance(self, value):
        if value < 0:
            raise ValueError("Баланс не может быть отрицательным.")
        self._balance = value

account = BankAccount(1000)
print(account.balance)  # 1000
account.balance = 500
print(account.balance)  # 500

В этом примере атрибут _balance объявлен как защищенный, чтобы предотвратить прямое изменение баланса извне. Вместо этого предоставляется свойство balance с геттерами и сеттерами, которые контролируют доступ к балансу.

Пояснение:

  1. Класс BankAccount:
    • Этот класс описывает банковский счет с балансом.
  2. Конструктор __init__:
    • При создании объекта класса BankAccount конструктор принимает параметр balance со значением по умолчанию равным нулю.
    • Значение параметра balance сохраняется в защищенном атрибуте _balance. Защита осуществляется добавлением одного символа подчеркивания перед именем атрибута, что указывает другим программистам, что данный атрибут предназначен для внутреннего использования.
  3. Свойство balance:
    • Используется декоратор @property для определения геттера (метода получения значения).
    • Геттер возвращает текущее значение защищенного поля _balance.
  4. Сеттер balance:
    • Используется декоратор @balance.setter для определения сеттера (метода установки значения).
    • Сеттер проверяет новое значение на допустимость: если оно меньше нуля, генерируется исключение ValueError.
    • Если значение корректно, оно присваивается защищенному полю _balance.
  5. Создание объекта и работа с ним:
    • Создается объект account класса BankAccount с начальным балансом 1000.
    • Для чтения текущего баланса используется синтаксис account.balance, который обращается к геттеру.
    • Для изменения баланса используется синтаксис account.balance = 500, который обращается к сеттеру.

Итог:

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

Для создания свойства-геттера над свойством ставится аннотация @property. Для создания свойства-сеттера над свойством устанавливается аннотация @имя_свойства_геттера.setter.

Источник: https://stepik.org/lesson/1583871/step/1?unit=1605226

Было ли это полезно?

0 / 0