SmartView · Python | Изучение Python
130 subscribers
373 photos
17 links
📖 Обучение языку программирования Python с самого начала: кратко, интересно и понятно!

📚 Мы стараемся преподавать самое важное в Python, чтобы вас не нагружать.

⚡️ Boost канала: https://t.me/boost/SV_Python

🍀 Желаем приятного изучения!
Download Telegram
Стратегия (Strategy)

Стратегия — это поведенческий паттерн, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Стратегия позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются.

class PaymentStrategy:
def pay(self, amount): pass

class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
return f"Оплата {amount} картой"

class ShoppingCart:
def __init__(self):
self.payment_strategy = None

def checkout(self, amount):
return self.payment_strategy.pay(amount)

cart = ShoppingCart()
cart.payment_strategy = CreditCardPayment()
print(cart.checkout(1000)) # Оплата 1000 картой
👍2👏1
Адаптер (Adapter)

Адаптер — это структурный паттерн, который позволяет объектам с несовместимыми интерфейсами работать вместе. Адаптер выступает прослойкой между двумя объектами, превращая вызовы одного в вызовы понятные другому.

from abc import ABC, abstractmethod

class DataProcessor(ABC):
@abstractmethod
def process(self, data): pass

class XMLProcessor:
def process_xml(self, xml_data):
return f"Обработка XML: {xml_data}"

class XMLAdapter(DataProcessor):
def __init__(self, xml_processor):
self.xml_processor = xml_processor

def process(self, data):
xml_data = f"<data>{data}</data>"
return self.xml_processor.process_xml(xml_data)

# Использование
xml_processor = XMLProcessor()
adapter = XMLAdapter(xml_processor)
print(adapter.process("John")) # Обработка XML: <data>John</data>
👍3🔥1
Декоратор (Decorator)

Декоратор — это структурный паттерн, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки». Декоратор предоставляет гибкую альтернативу наследованию для расширения функциональности.

class Coffee:
def cost(self): return 2.0
def desc(self): return "Кофе"

class MilkDecorator:
def __init__(self, coffee):
self.coffee = coffee
def cost(self): return self.coffee.cost() + 0.5
def desc(self): return self.coffee.desc() + " + молоко"

class SugarDecorator:
def __init__(self, coffee):
self.coffee = coffee
def cost(self): return self.coffee.cost() + 0.3
def desc(self): return self.coffee.desc() + " + сахар"

# Использование
coffee = SugarDecorator(MilkDecorator(Coffee()))
print(f"{coffee.desc()} = {coffee.cost()} руб.")
# Кофе + молоко + сахар = 2.8 руб
👍4🔥1
Создание пользовательских исключений

Пользовательские исключения делают код более читаемым и позволяют точно идентифицировать ошибки вашего приложения, отличая их от стандартных исключений Python.

Базовый пользовательский класс исключения:
class BankError(Exception):
pass

class InsufficientFundsError(BankError):
def __init__(self, balance, amount):
super().__init__(f"Баланс {balance}, нужно {amount}")

class Account:
def __init__(self, balance=0):
self.balance = balance

def withdraw(self, amount):
if amount > self.balance:
raise InsufficientFundsError(self.balance, amount)
self.balance -= amount

# Использование
acc = Account(100)
try:
acc.withdraw(200)
except InsufficientFundsError as e:
print(f"Ошибка: {e}") # Баланс 100, нужно 200
👍2
Наследование от встроенных исключений

Правильное наследование исключений:
В Python все исключения наследуются от базового класса Exception. При создании пользовательских исключений важно правильно выбрать родительский класс для совместимости.

class ValidationError(ValueError):
"""Наследуем от ValueError для совместимости"""
pass

def validate_age(age):
if age < 0:
raise ValidationError("Возраст не может быть отрицательным")

try:
validate_age(-5)
except ValueError as e: # Поймает ValidationError
print(f"Ошибка: {e}")
👍2
Обработка исключений в методах

Два подхода:
1. Обработка внутри метода
2. Проброс исключения наружу

Пример:
class FileReader:
def read_safe(self, filename):
"""Обработка внутри метода"""
try:
with open(filename) as f:
return f.read()
except FileNotFoundError:
return "" # Возвращаем значение по умолчанию

def read_strict(self, filename):
"""Проброс исключения наружу"""
with open(filename) as f:
return f.read() # FileNotFoundError пройдет выше

reader = FileReader()
content = reader.read_safe("нет_файла.txt") # Вернет ""
# reader.read_strict("нет_файла.txt") # Вызовет FileNotFoundError
👍1👏1
Контекстные менеджеры с классами

Классы с enter и exit:
Позволяют создавать свои контекстные менеджеры.

Пример:
class Timer:
"""Измеряет время выполнения блока кода"""
def __enter__(self):
import time
self.start = time.time()

def __exit__(self, *args):
import time
print(f"Выполнено за: {time.time() - self.start:.2f} сек.")

with Timer():
import time
time.sleep(1) # Вывод: Выполнено за: 1.00 сек.
👍2
Паттерн "Фабрика исключений"

Централизованное создание исключений:
Упрощает управление ошибками в больших проектах.

Пример:
class ExceptionFactory:
"""Создает стандартизированные исключения"""
@staticmethod
def validation_error(field, message):
return ValueError(f"[VALIDATION] {field}: {message}")

@staticmethod
def business_error(code, message):
error = RuntimeError(message)
error.code = code
return error

# Использование
try:
raise ExceptionFactory.validation_error("email", "Неверный формат")
except ValueError as e:
print(f"Ошибка: {e}") # [VALIDATION] email: Неверный формат
👍2
Модуль unittest для тестирования классов

Базовое тестирование:
Unittest — встроенный модуль для тестирования.

Пример:
import unittest

class Calculator:
def add(self, a, b):
return a + b

class TestCalculator(unittest.TestCase):
def setUp(self):
"""Подготовка перед каждым тестом"""
self.calc = Calculator()

def test_add_positive(self):
self.assertEqual(self.calc.add(2, 3), 5)

def test_add_negative(self):
self.assertEqual(self.calc.add(-1, -1), -2)

if __name__ == "__main__":
unittest.main()
👍2
Mock объекты для тестирования

Изоляция зависимостей:
Mock-объекты имитируют реальные объекты для тестирования.

Пример:
from unittest.mock import Mock

class WeatherService:
def __init__(self, api):
self.api = api

def get_temp(self, city):
return self.api.fetch(city)['temp']

# Тест
mock_api = Mock()
mock_api.fetch.return_value = {'temp': 25}
service = WeatherService(mock_api)

result = service.get_temp("Москва")
assert result == 25
mock_api.fetch.assert_called_once_with("Москва")
👍1👏1
Тестирование наследования

Проверка полиморфного поведения:
Тестируем, что дочерние классы правильно переопределяют методы.

Пример:
class Animal:
def speak(self):
return "Звук"

class Dog(Animal):
def speak(self):
return "Гав"

class TestAnimals(unittest.TestCase):
def test_inheritance(self):
dog = Dog()
self.assertEqual(dog.speak(), "Гав")
self.assertIsInstance(dog, Animal)
👍1👏1
Тестирование приватных методов

Лучше тестировать через публичный интерфейс:
Но иногда нужен прямой доступ.

Пример:
class Validator:
def _validate_email(self, email):
return "@" in email

def register_user(self, email):
if not self._validate_email(email):
raise ValueError("Неверный email")
return True

# Тестируем через публичный метод
validator = Validator()
self.assertTrue(validator.register_user("test@mail.com"))
with self.assertRaises(ValueError):
validator.register_user("invalid-email")
👍2
Паттерн "Тестовые дублеры"

Разные типы дублеров:
Mock, Stub, Fake, Spy для разных задач.

Пример:
from unittest.mock import Mock

class Database:
def get_user(self, user_id):
# Реальный код работы с БД
pass

class UserService:
def __init__(self, db):
self.db = db

def get_user_name(self, user_id):
user = self.db.get_user(user_id)
return user['name'] if user else None

# Используем Mock как тестовый дублер
mock_db = Mock()
mock_db.get_user.return_value = {'name': 'Анна', 'id': 1}
service = UserService(mock_db)

assert service.get_user_name(1) == 'Анна'
👍1🔥1
Дескрипторы

Управление доступом к атрибутам:
Дескрипторы контролируют, как устанавливаются и получаются значения атрибутов.

Пример:
class PositiveNumber:
"""Дескриптор для положительных чисел"""
def __set__(self, obj, value):
if value < 0:
raise ValueError("Число должно быть положительным")
obj.__dict__[self.name] = value

def __set_name__(self, owner, name):
self.name = name

class Account:
balance = PositiveNumber()

def __init__(self, balance):
self.balance = balance # Вызовет __set__

acc = Account(100) # OK
# acc.balance = -50 # ValueError: Число должно быть положительным
👍2
Слоты slots

Оптимизация памяти:
Ограничивает набор атрибутов и экономит память.

Пример:
class Point:
__slots__ = ['x', 'y'] # Только эти атрибуты разрешены

def __init__(self, x, y):
self.x = x
self.y = y

p = Point(1, 2)
print(p.x, p.y) # 1 2
# p.z = 3 # AttributeError: 'Point' object has no attribute 'z'
👍3
Абстрактные методы

Принудительная реализация:
Абстрактные методы должны быть реализованы в дочерних классах.

Пример:
from abc import ABC, abstractmethod

class Shape(ABC):
@abstractmethod
def area(self):
"""Должен быть реализован в дочерних классах"""
pass

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def area(self): # Обязательная реализация
return 3.14 * self.radius ** 2

# Shape() # TypeError: нельзя создать экземпляр абстрактного класса
circle = Circle(5) # OK
print(circle.area()) # 78.5
👍2
Протоколы и интерфейсы

Неявные интерфейсы Python:
Если объект имеет нужные методы, он соответствует протоколу.

Пример:
from typing import Protocol

class Drawable(Protocol):
def draw(self) -> str: ...

class Circle:
def draw(self):
return "Рисую круг"

class Square:
def draw(self):
return "Рисую квадрат"

def render(obj: Drawable):
return obj.draw()

print(render(Circle())) # "Рисую круг"
print(render(Square())) # "Рисую квадрат"
👍3
Миксины (Mixins)

Множественное наследование для функциональности:
Миксины добавляют возможности без изменения основной логики.

Пример:
class JSONSerializable:
"""Миксин для сериализации в JSON"""
def to_json(self):
import json
return json.dumps(self.__dict__)

class Timestamped:
"""Миксин для добавления временных меток"""
def __init__(self):
from datetime import datetime
self.created_at = datetime.now()

class User(Timestamped, JSONSerializable):
"""Класс пользователя с миксинами"""
def __init__(self, name, email):
super().__init__() # Вызываем __init__ миксинов
self.name = name
self.email = email

user = User("Анна", "anna@example.com")
print(user.to_json()) # JSON с created_at, name, email
👍4
С Новым 2026 годом! Пусть этот год принесет вам радость, счастье и исполнение всех заветных желаний. Пусть каждый день будет наполнен яркими моментами, новыми достижениями и приятными сюрпризами.

@SV_Python
🎄5🔥1🤩1