Python Senior
Вопросы ловушки
Ответы
Отлично, сделаем **те же самые ООП-ловушки**, но **максимально просто и на Python**, так как именно так их лучше объяснять **на собеседовании**. Ниже: 👉 **вопрос → плохой ответ → правильный ответ → простой код** --- # 1️⃣ «Квадрат — это прямоугольник?» ### ❌ Ловушка ```python class Rectangle: def set_width(self, w): self.w = w def set_height(self, h): self.h = h ``` ```python class Square(Rectangle): def set_width(self, w): self.w = self.h = w def set_height(self, h): self.w = self.h = h ``` ```python def resize(rect): rect.set_width(5) rect.set_height(10) return rect.w * rect.h ``` ```python resize(Rectangle()) # 50 resize(Square()) # 100 ❌ ``` ### ✅ Вывод > Наследник **изменил поведение** → нарушен контракт → **нарушение LSP** --- # 2️⃣ «Зачем нужна композиция, если есть наследование?» ### ❌ Плохо (наследование) ```python class Engine(Car): # ❌ двигатель — не машина pass ``` ### ✅ Хорошо (композиция) ```python class Engine: def start(self): print("engine started") class Car: def __init__(self): self.engine = Engine() ``` **Ключевая мысль:** > Если это **has-a**, а не **is-a** → композиция --- # 3️⃣ «Что такое полиморфизм?» ### ❌ Плохой ответ > «Это перегрузка методов» ### ✅ Правильный ответ + код ```python class Cat: def speak(self): return "meow" class Dog: def speak(self): return "woof" ``` ```python def make_sound(animal): print(animal.speak()) ``` ```python make_sound(Cat()) make_sound(Dog()) ``` 👉 **Один интерфейс — разное поведение** --- # 4️⃣ «Что такое контракт класса?» ### Пример контракта ```python class BankAccount: def withdraw(self, amount): """ amount > 0 balance >= amount """ ``` Если наследник нарушает это: ```python class FakeAccount(BankAccount): def withdraw(self, amount): self.balance -= amount * 10 # ❌ ``` 👉 Контракт нарушен 👉 Полиморфизм сломан --- # 5️⃣ «Когда наследование — зло?» ### ❌ Хрупкий базовый класс ```python class Base: def process(self): self.step1() self.step2() class Child(Base): def step2(self): raise Exception("oops") ``` 👉 Изменение `Base` может **сломать всех наследников** --- # 6️⃣ «Инкапсуляция — это private?» ### ❌ Неправильно ```python class User: balance = 100 # открыт всем ``` ### ✅ Правильно ```python class User: def __init__(self): self._balance = 100 def pay(self, amount): if amount <= self._balance: self._balance -= amount ``` > Инкапсуляция = **контроль доступа**, а не просто `_` --- # 7️⃣ «Что важнее — данные или поведение?» ### ❌ Плохо (анемичная модель) ```python class Order: total = 100 ``` ```python def apply_discount(order): order.total *= 0.9 ``` ### ✅ Хорошо ```python class Order: def __init__(self, total): self.total = total def apply_discount(self): self.total *= 0.9 ``` 👉 **Объект управляет своим состоянием** --- # 8️⃣ «Можно ли жить без ООП?» ### Да 🙂 ```python def area(width, height): return width * height ``` 👉 Для простых задач **ООП избыточно** **Правильный ответ:** > ООП — инструмент, а не обязательство --- # 9️⃣ «Что такое Бог-объект?» ```python class SystemManager: def login(self): ... def send_email(self): ... def save_to_db(self): ... def calculate_salary(self): ... def render_html(self): ... ``` ❌ * нарушен SRP * сложно тестировать * сложно поддерживать --- # 🔟 «Почему композиция лучше наследования?» ### Наследование (жёстко) ```python class FileLogger(Logger): ... ``` ### Композиция (гибко) ```python class Service: def __init__(self, logger): self.logger = logger ``` ```python service = Service(FileLogger()) service = Service(DbLogger()) ``` --- # 🧠 Как отвечать на собеседовании (коротко) Если вопрос кажется простым — говори про: * **поведение** * **контракты** * **is-a vs has-a** * **LSP** * **composition over inheritance** --- ## Мини-шпаргалка ```text is-a → наследование has-a → композиция наследник не должен ломать ожидания ООП = поведение + ответственность классы ≠ ООП ``` --- Если хочешь, дальше могу: * разобрать **эти же ловушки на задачах с кодом** * сделать **чеклист ответов для собеседования** * разобрать **типичные ошибки Python-разработчиков** * провести **мок-собеседование** Скажи, что дальше 👍