← Назад к вопросам
Как используешь инкапсуляцию на практике?
1.8 Middle🔥 161 комментариев
#Python Core#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Инкапсуляция на практике
Инкапсуляция — это принцип скрытия внутренней реализации объекта и предоставления контролируемого доступа к его состоянию и поведению. В Python это делается через соглашение о названиях и использование свойств (properties).
Основные уровни доступа
В Python нет строгих модификаторов доступа (как public/private в Java), но есть соглашения:
class BankAccount:
# Публичный атрибут
account_number = "123456"
# Защищённый атрибут (соглашение: используй осторожно)
_balance = 1000
# Приватный атрибут (Name mangling, двойное подчёркивание)
__pin = "1234"
1. Приватные атрибуты с двойным подчёркиванием
Двойное подчёркивание включает name mangling — атрибут переименовывается во время компиляции:
class BankAccount:
def __init__(self, balance):
self.__balance = balance
def get_balance(self):
return self.__balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
account = BankAccount(1000)
print(account.get_balance()) # 1000
2. Свойства (Properties) — правильный способ
Используй @property для контролируемого доступа к атрибутам:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Температура ниже абсолютного нуля")
self._celsius = value
@property
def fahrenheit(self):
return self._celsius * 9/5 + 32
temp = Temperature(25)
print(temp.celsius) # 25
print(temp.fahrenheit) # 77.0
temp.celsius = 30 # Работает setter с валидацией
3. Практический пример: User с инкапсуляцией
import re
from datetime import datetime
class User:
def __init__(self, name, email, password):
self._name = name
self._email = email
self.__password_hash = hash(password)
self._created_at = datetime.now()
self._login_attempts = 0
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value or len(value) < 2:
raise ValueError("Имя должно быть минимум 2 символа")
self._name = value
@property
def email(self):
return self._email
@email.setter
def email(self, value):
if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$', value):
raise ValueError("Неправильный формат email")
self._email = value
def set_password(self, old_password, new_password):
if hash(old_password) != self.__password_hash:
self._login_attempts += 1
if self._login_attempts >= 3:
raise PermissionError("Слишком много попыток")
raise ValueError("Неправильный пароль")
self.__password_hash = hash(new_password)
self._login_attempts = 0
return True
def verify_password(self, password):
return hash(password) == self.__password_hash
user = User("Иван", "ivan@example.com", "secret123")
print(user.name) # Иван
user.name = "Петр" # ОК
user.verify_password("secret123") # True
4. Инкапсуляция с наследованием
class Animal:
def __init__(self, name):
self._name = name
self.__species = None
def _get_sound(self):
return "..."
class Dog(Animal):
def _get_sound(self):
return "Гав!"
def bark(self):
return self._get_sound()
dog = Dog("Шарик")
print(dog.bark()) # Гав!
5. Использование slots для оптимизации
class Point:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
point = Point(10, 20)
print(point.x, point.y) # 10 20
Резюме
- __private — Name mangling, скрывает от случайного доступа
- _protected — Соглашение для наследников и внутреннего использования
- @property — Правильный способ контроля доступа с валидацией
- slots — Оптимизация для часто создаваемых объектов
- Правило: Минимум публичного интерфейса, максимум инкапсуляции