Anonymous Quiz
61%
read()
6%
readline()
13%
readall()
20%
readlines()
❤3💊1
Существует множество модулей и библиотек для тестирования, которые помогают автоматизировать процесс тестирования, обнаруживать ошибки и обеспечивать качество кода. Некоторые из наиболее популярных модулей и библиотек для тестирования:
Встроенные модули
import unittest
class TestMathOperations(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 1, 2)
if __name__ == '__main__':
unittest.main()
def add(a, b):
"""
Возвращает сумму a и b.
>>> add(1, 2)
3
>>> add(-1, 1)
0
"""
return a + b
if name == '__main__':
import doctest
doctest.testmod()
Внешние библиотеки
def add(a, b):
return a + b
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
if name == '__main__':
import pytest
pytest.main()
nose
.unittest
и расширяет его возможности.import unittest
class TestMathOperations(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 1, 2)
if name == '__main__':
import nose2
nose2.main()
from hypothesis import given
from hypothesis.strategies import integers
def add(a, b):
return a + b
@given(integers(), integers())
def test_add(x, y):
assert add(x, y) == x + y
if name == '__main__':
import pytest
pytest.main()
4️⃣ mock (unittest.mock)
➕ Библиотека для создания фиктивных объектов и имитации поведения зависимостей.
➕ Включена в стандартную библиотеку Python начиная с версии 3.3 как unittest.mock.
import unittest
from unittest.mock import patch
def fetch_data():
# Представим, что эта функция делает запрос к внешнему API
return "Real data"
class TestFetchData(unittest.TestCase):
@patch('main.fetch_data', return_value="Mock data")
def test_fetch_data(self, mock_fetch):
result = fetch_data()
self.assertEqual(result, "Mock data")
if:
== 'main':
unittest.main()
[tox]
envlist = py36, py37, py38
[testenv]
deps = pytest
commands = pytest
coverage run -m pytest
coverage report
coverage html # Создает отчет в формате HTML
Выбор инструмента для тестирования зависит от ваших потребностей и предпочтений. Стандартные модули, такие как
unittest
и doctest
, предоставляют базовые возможности для тестирования, в то время как внешние библиотеки, такие как pytest
, nose2
и hypothesis
, предлагают более мощные и гибкие инструменты для написания и выполнения тестов. Использование библиотек для измерения покрытия кода, таких как coverage
, помогает убедиться, что ваш код полностью протестирован.Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤1🔥1
Monkey patching — это техника программирования, при которой поведение библиотеки или модуля изменяется во время выполнения программы. Этот метод позволяет динамически изменять или расширять код, написанный другими разработчиками, без изменения исходного кода самой библиотеки или модуля.
Основные особенности:
Пример использования Monkey Patching
Оригинальная функция
Допустим, у нас есть модуль
math_operations.py
с функцией add
:# math_operations.py
def add(a, b):
return a + b
Monkey Patching
Изменить функцию
add
, чтобы она вместо сложения выполняла вычитание. Мы можем сделать это с помощью monkey patching:import math_operations
# Оригинальная функция
print(math_operations.add(5, 3)) # Вывод: 8
# Monkey patching
def new_add(a, b):
return a - b
math_operations.add = new_add
# После monkey patching
print(math_operations.add(5, 3)) # Вывод: 2
Пример с использованием стандартной библиотеки
Где изменим поведение метода
str.upper
:# Оригинальный метод
print("hello".upper()) # Вывод: HELLO
# Monkey patching
def new_upper(self):
return self.lower()
str.upper = new_upper
# После monkey patching
print("hello".upper()) # Вывод: hello
Применение Monkey Patching в тестировании
Часто используется в тестировании для имитации поведения зависимостей или для замены реальных объектов на фиктивные (mock) объекты.
import unittest
from unittest.mock import patch
class ExternalService:
def fetch_data(self):
# Представим, что эта функция делает запрос к внешнему API
return "Real data"
def process_data():
service = ExternalService()
return service.fetch_data()
class TestProcessData(unittest.TestCase):
@patch('__main__.ExternalService.fetch_data', return_value="Mock data")
def test_process_data(self, mock_fetch_data):
result = process_data()
self.assertEqual(result, "Mock data")
if __name__ == '__main__':
unittest.main()
В этом примере:
unittest.mock.patch
для замены метода fetch_data
класса ExternalService
на фиктивный метод, возвращающий "Mock data".process_data
возвращает подделанные данные вместо реальных данных.Предостережения при его использовании
Хотя monkey patching может быть полезным, оно также может привести к проблемам, если использовать его неправильно:
Monkey patching — мощная техника, которая позволяет динамически изменять поведение модулей и библиотек во время выполнения программы. Она может быть полезна для исправления ошибок, добавления функциональности или создания фиктивных объектов для тестирования. Однако использовать monkey patching следует осторожно, чтобы избежать проблем с отладкой и неожиданным поведением программы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥3❤1
Anonymous Quiz
76%
Словарь будет распакован в именованные аргументы
5%
Произойдет ошибка времени выполнения
9%
Словарь будет преобразован в список
9%
Произойдет ошибка компиляции
👍7💊2
Реализация тестов — важная часть процесса разработки программного обеспечения, которая помогает обеспечить корректность и надёжность кода. Для написания тестов обычно используется модуль
unittest
, который является стандартным модулем для тестирования и поставляется вместе. Другие популярные библиотеки для тестирования включают pytest
и nose
.Использование модуля
unittest
Предоставляет инструменты для создания и выполнения тестов. Давайте рассмотрим основные шаги для написания тестов с использованием
unittest
.Основные шаги для написания тестов:
unittest.TestCase
.test_
.assert
) используются для проверки условий, таких как assertEqual
, assertTrue
, assertFalse
, assertRaises
и другие.Примеры использования:
Допустим, у нас есть простая функция для сложения двух чисел:
# Пример функции в файле my_module.py
def add(a, b):
return a + b
Теперь мы напишем тесты для этой функции:
# Пример теста в файле test_my_module.py
import unittest
from my_module import add
class TestAddFunction(unittest.TestCase):
def test_add_integers(self):
self.assertEqual(add(1, 2), 3)
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(-1, -1), -2)
def test_add_floats(self):
self.assertAlmostEqual(add(1.1, 2.2), 3.3)
def test_add_strings(self):
self.assertEqual(add('a', 'b'), 'ab')
if __name__ == '__main__':
unittest.main()
Запуск тестов
Тесты можно запускать разными способами. Вот несколько способов:
python -m unittest test_my_module.py
Просто запустите файл
test_my_module.py
как обычный Python-скрипт.python test_my_module.py
Использование
pytest
Это мощная библиотека для тестирования, которая упрощает написание и выполнение тестов. Она поддерживает функциональные и модульные тесты и имеет лаконичный синтаксис.
# Пример функции в файле my_module.py
def add(a, b):
return a + b
Запуск тестов с
pytest
Убедитесь, что
pytest
установлен. Вы можете установить его с помощью pip:pip install pytest
Запуск тестов:
pytest test_my_module.py
Преимущества:
Написание тестов — важная часть разработки программного обеспечения, которая помогает обнаруживать ошибки и обеспечивать качество кода. Для тестирования можно использовать стандартный модуль
unittest
или более мощную библиотеку pytest
. Основные шаги включают создание тестовых классов, написание тестовых методов, использование утверждений и запуск тестов. Выбор инструмента зависит от ваших предпочтений и требований проекта, но оба подхода обеспечивают эффективное тестирование вашего кода.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1😁1🎉1
Если не использовать конструкцию
with
, гарантировать закрытие файла можно несколькими способами, в частности, используя конструкцию try-finally
или модуль contextlib
.Использование
try-finally
Позволяет обеспечить закрытие файла даже в случае возникновения исключения. В блоке
finally
можно указать код, который должен выполниться независимо от того, было ли исключение в блоке try
или нет.file = open('example.txt', 'r')
try:
content = file.read()
print(content)
finally:
file.close()
В этом примере:
try
.try
или нет, файл будет закрыт в блоке finally
.Использование модуля
contextlib
Предоставляет утилиты для работы с контекстными менеджерами. Одной из таких утилит является функция
contextlib.closing
, которая может быть использована для автоматического закрытия объекта, поддерживающего метод close
.from contextlib import closing
file = open('example.txt', 'r')
with closing(file) as f:
content = f.read()
print(content)
В этом примере:
closing
.with
завершается, closing
автоматически закрывает файл.Создание пользовательского контекстного менеджера
Также можно создать свой собственный контекстный менеджер с помощью класса, который реализует методы
__enter__
и exit.class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_value, traceback):
self.file.close()
# Использование
with FileManager('example.txt', 'r') as file:
content = file.read()
print(content)
В этом примере:
FileManager
реализует методы enter и exit.Гарантировать закрытие файла можно несколькими способами, помимо использования конструкции
with
:try-finally
, чтобы файл всегда закрывался независимо от возникновения исключений.contextlib
и его утилиту closing
для автоматического закрытия файла.Эти методы обеспечивают надёжное управление ресурсами и предотвращают утечки ресурсов, которые могут возникнуть при некорректном закрытии файлов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2🔥1
Anonymous Quiz
10%
возникнет исключение
16%
вернется None
24%
функция завершится без результата
50%
создастся генератор
Python предоставляет мощные встроенные функции и модули для работы с файлами. Основные операции включают открытие, чтение, запись и закрытие файлов.
Открытие файла
Файл можно открыть с помощью встроенной функции
open()
. Эта функция возвращает объект файла, который затем можно использовать для выполнения различных операций с файлом.Синтаксис функции
open()
:file_object = open(file_name, mode)
file_name
: Имя файла, который вы хотите открыть.mode
: Режим, в котором вы хотите открыть файл. Основные режимы включают:'r'
: чтение (по умолчанию)'w'
: запись (содержимое файла будет удалено)'a'
: добавление (новые данные будут добавлены в конец файла)'b'
: бинарный режим (добавляется к основному режиму, например 'rb'
или 'wb'
)Примеры:
Чтение файла
# Открытие файла в режиме чтения
with open('example.txt', 'r') as file:
content = file.read()
print(content)
Запись в файл
# Открытие файла в режиме записи
with open('example.txt', 'w') as file:
file.write('Hello, world!')
Добавление в файл
# Открытие файла в режиме добавления
with open('example.txt', 'a') as file:
file.write('\nAppended text.')
Чтение из файла
Файловый объект предоставляет несколько методов для чтения данных:
read(size=-1)
: Читает весь файл или size
байт, если указан.readline(size=-1)
: Читает одну строку или size
байт, если указан.readlines()
: Читает все строки файла и возвращает их в виде списка.Примеры:
Чтение всего файла
with open('example.txt', 'r') as file:
content = file.read()
print(content)
Чтение файла построчно
with open('example.txt', 'r') as file:
for line in file:
print(line, end='') # `end=''` чтобы избежать двойного переноса строки
Чтение файла в список строк
with open('example.txt', 'r') as file:
lines = file.readlines()
print(lines)
Запись в файл
Файловый объект также предоставляет методы для записи данных:
write(string)
: Записывает строку в файл.writelines(lines)
: Записывает список строк в файл.Примеры:
Запись строки в файл
with open('example.txt', 'w') as file:
file.write('Hello, world!')
Запись списка строк в файл
lines = ['First line\n', 'Second line\n', 'Third line\n']
with open('example.txt', 'w') as file:
file.writelines(lines)
Использование менеджеров контекста (
with
)Она автоматически закрывает файл после выхода из блока
with
, даже если возникло исключение.with open('example.txt', 'r') as file:
content = file.read()
print(content)
Закрытие файла
Если файл открыт без использования
with
, его нужно закрыть вручную с помощью метода close()
.file = open('example.txt', 'r')
content = file.read()
print(content)
file.close()
Дополнительные операции с файлами
Модуль
os
предоставляет функции для работы с файловой системой, такие как переименование, удаление и создание директорий.Примеры:
Переименование файла
import os
os.rename('example.txt', 'new_example.txt')
Удаление файла
import os
os.remove('new_example.txt')
Создание директории
import os
os.mkdir('new_directory')
Удаление директории
import os
os.rmdir('new_directory')
Python предоставляет богатые возможности для работы с файлами, начиная с простого чтения и записи и заканчивая сложными операциями с файловой системой. Использование менеджеров контекста (
with
) обеспечивает безопасное и эффективное управление файлами.Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2🔥2
Принцип SLAP (Single Level of Abstraction Principle) относится к принципам чистого кода и разработки программного обеспечения. Он заключается в том, что каждый метод или функция должны работать на одном уровне абстракции.
Помогает сделать код более читаемым, поддерживаемым и легким для понимания. Когда код организован таким образом, что каждая функция или метод выполняет задачи только на одном уровне абстракции, разработчики могут легче следить за логикой программы и быстрее находить ошибки.
При разработке ПО, вы должны стремиться к тому, чтобы методы и функции содержали действия только одного типа или уровня абстракции. Это может быть достигнуто через декомпозицию задач на более мелкие подзадачи и создание соответствующих методов для каждой подзадачи.
def process_order(order):
# Проверка наличия товара на складе
for item in order['items']:
if not warehouse_has_item(item):
raise Exception("Товара нет на складе")
# Расчет общей стоимости заказа
total_price = 0
for item in order['items']:
total_price += item['price'] * item['quantity']
# Создание записи в базе данных
save_order_to_db(order, total_price)
# Отправка уведомления клиенту
send_confirmation_email(order['customer_email'])
Эта функция выполняет несколько задач на разных уровнях абстракции: проверка наличия товара, расчет стоимости, работа с базой данных, отправка email. Это нарушает принцип SLAP.
def process_order(order):
check_items_availability(order['items'])
total_price = calculate_total_price(order['items'])
save_order(order, total_price)
notify_customer(order['customer_email'])
def check_items_availability(items):
for item in items:
if not warehouse_has_item(item):
raise Exception("Товара нет на складе")
def calculate_total_price(items):
total_price = 0
for item in items:
total_price += item['price'] * item['quantity']
return total_price
def save_order(order, total_price):
save_order_to_db(order, total_price)
def notify_customer(email):
send_confirmation_email(email)
Принцип SLAP означает, что каждая функция должна выполнять задачи только на одном уровне абстракции. Это делает код более чистым и легким для понимания.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2🔥1
Anonymous Quiz
17%
ничего не произойдет
17%
возникнет ошибка компиляции
23%
возникнет исключение RuntimeError
43%
значение ключа изменится
👍11😁2
Кодовые метрики когезии (cohesion) и связи (coupling) играют ключевую роль в проектировании программного обеспечения. Давайте разберем их более подробно.
Когезия (Cohesion)
Это мера того, насколько сильно элементы внутри модуля связаны друг с другом. Высокая когезия означает, что элементы модуля работают вместе для выполнения одной задачи.
class Utility:
def calculate_tax(self, amount):
# Код для расчета налога
pass
def send_email(self, email, message):
# Код для отправки email
pass
def generate_report(self, data):
# Код для генерации отчета
pass
Этот класс выполняет несколько несвязанных задач, что снижает когезию.
class TaxCalculator:
def calculate_tax(self, amount):
# Код для расчета налога
pass
class EmailSender:
def send_email(self, email, message):
# Код для отправки email
pass
class ReportGenerator:
def generate_report(self, data):
# Код для генерации отчета
pass
Каждый класс выполняет одну четко определенную задачу, что повышает когезию.
Связь (Coupling)
Это мера зависимости между модулями. Низкая связь означает, что изменения в одном модуле минимально влияют на другие модули.
class OrderProcessor:
def __init__(self):
self.tax_calculator = TaxCalculator()
self.email_sender = EmailSender()
def process_order(self, order):
tax = self.tax_calculator.calculate_tax(order.amount)
self.email_sender.send_email(order.customer_email, "Order processed")
OrderProcessor сильно зависит от TaxCalculator и EmailSender.
class OrderProcessor:
def __init__(self, tax_calculator, email_sender):
self.tax_calculator = tax_calculator
self.email_sender = email_sender
def process_order(self, order):
tax = self.tax_calculator.calculate_tax(order.amount)
self.email_sender.send_email(order.customer_email, "Order processed")
В этом примере зависимости инъектируются через конструктор, что уменьшает связь между модулями и позволяет их легче тестировать и заменять.
Когезия делает модули логичными и понятными, а низкая связь позволяет модулям работать независимо друг от друга.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥2❤1
Anonymous Quiz
36%
None
17%
undefined
6%
null
41%
невозможно использовать неинициализированные переменные
Порождающий паттерн (creational pattern) — это тип шаблонов проектирования, который предоставляет различные способы создания объектов, помогая отделить логику создания объектов от их основного использования. Порождающие паттерны помогают сделать систему более гибкой и независимой от конкретных классов, которые она использует.
Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру.
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
# Использование
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True
Определяет интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов.
from abc import ABC, abstractmethod
class Product(ABC):
@abstractmethod
def operation(self):
pass
class ConcreteProductA(Product):
def operation(self):
return "Result of ConcreteProductA"
class ConcreteProductB(Product):
def operation(self):
return "Result of ConcreteProductB"
class Creator(ABC):
@abstractmethod
def factory_method(self):
pass
def some_operation(self):
product = self.factory_method()
return f"Creator: The same creator's code has just worked with {product.operation()}"
class ConcreteCreatorA(Creator):
def factory_method(self):
return ConcreteProductA()
class ConcreteCreatorB(Creator):
def factory_method(self):
return ConcreteProductB()
# Использование
creator = ConcreteCreatorA()
print(creator.some_operation())
creator = ConcreteCreatorB()
print(creator.some_operation())
Порождающие паттерны проектирования помогают создавать объекты в системе, абстрагируя логику их создания. Они делают код более гибким и независимым от конкретных классов, упрощая поддержку и расширение системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1🎉1
Anonymous Quiz
24%
xml.dom
10%
xml.sax
33%
xml.etree.ElementTree
33%
re
👾5❤1
Forwarded from Идущий к IT
10$ за техническое собеседование на английском языке:
1. Отправьте запись технического собеседования на английском языке файлом на этот аккаунт
2. Добавьте ссылку на вакансию или пришлите название компании и должность
3. Напишите номер кошелка USDT (Tether) на который отправить 10$
🛡 Важно:
– Запись будет использована только для сбора данных о вопросах
– Вы останетесь анонимны
– Запись нигде не будет опубликована
🤝 Условия:
– Внятный звук, различимая речь
– Допустимые профессии:
• Любые программисты
• DevOps
• Тестировщики
• Дата сайнтисты
• Бизнес/Системные аналитики
• Прожекты/Продукты
• UX/UI и продукт дизайнеры
1. Отправьте запись технического собеседования на английском языке файлом на этот аккаунт
2. Добавьте ссылку на вакансию или пришлите название компании и должность
3. Напишите номер кошелка USDT (Tether) на который отправить 10$
– Запись будет использована только для сбора данных о вопросах
– Вы останетесь анонимны
– Запись нигде не будет опубликована
– Внятный звук, различимая речь
– Допустимые профессии:
• Любые программисты
• DevOps
• Тестировщики
• Дата сайнтисты
• Бизнес/Системные аналитики
• Прожекты/Продукты
• UX/UI и продукт дизайнеры
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4👀1
Абстрактная фабрика (Abstract Factory) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов. Этот паттерн используется, когда система должна быть независимой от способа создания, композиции и представления своих продуктов.
Определяет интерфейсы для создания абстрактных продуктов. Конкретные фабрики реализуют эти интерфейсы, создавая конкретные продукты.
Рассмотрим пример абстрактной фабрики для создания семейств продуктов
Chair
и Sofa
для разных стилей мебели (Modern и Victorian).from abc import ABC, abstractmethod
# Абстрактные продукты
class Chair(ABC):
@abstractmethod
def sit_on(self) -> str:
pass
class Sofa(ABC):
@abstractmethod
def lie_on(self) -> str:
pass
# Конкретные продукты
class ModernChair(Chair):
def sit_on(self) -> str:
return "Sitting on a modern chair."
class VictorianChair(Chair):
def sit_on(self) -> str:
return "Sitting on a Victorian chair."
class ModernSofa(Sofa):
def lie_on(self) -> str:
return "Lying on a modern sofa."
class VictorianSofa(Sofa):
def lie_on(self) -> str:
return "Lying on a Victorian sofa."
# Абстрактная фабрика
class FurnitureFactory(ABC):
@abstractmethod
def create_chair(self) -> Chair:
pass
@abstractmethod
def create_sofa(self) -> Sofa:
pass
# Конкретные фабрики
class ModernFurnitureFactory(FurnitureFactory):
def create_chair(self) -> Chair:
return ModernChair()
def create_sofa(self) -> Sofa:
return ModernSofa()
class VictorianFurnitureFactory(FurnitureFactory):
def create_chair(self) -> Chair:
return VictorianChair()
def create_sofa(self) -> Sofa:
return VictorianSofa()
# Клиентский код
def client_code(factory: FurnitureFactory):
chair = factory.create_chair()
sofa = factory.create_sofa()
print(chair.sit_on())
print(sofa.lie_on())
# Использование
if __name__ == "__main__":
print("Modern furniture:")
client_code(ModernFurnitureFactory())
print("\nVictorian furniture:")
client_code(VictorianFurnitureFactory())
Преимущества:
Недостатки:
Абстрактная фабрика помогает создавать семейств продуктов, делая код более гибким и расширяемым.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3
Паттерн "Построитель" (Builder) — это порождающий паттерн проектирования, который позволяет создавать сложные объекты поэтапно. В отличие от других порождающих паттернов, Builder предоставляет возможность постепенно конструировать объект, контролируя процесс его создания на каждом этапе. Этот паттерн особенно полезен, когда нужно создать объект с различными конфигурациями или когда создание объекта требует много шагов.
Паттерн состоит из следующих компонентов:
from abc import ABC, abstractmethod
# Продукт
class Car:
def __init__(self):
self.parts = []
def add_part(self, part):
self.parts.append(part)
def list_parts(self):
return ", ".join(self.parts)
# Интерфейс Построителя
class CarBuilder(ABC):
@abstractmethod
def produce_engine(self):
pass
@abstractmethod
def produce_wheels(self):
pass
@abstractmethod
def produce_body(self):
pass
# Конкретный Построитель
class SportsCarBuilder(CarBuilder):
def __init__(self):
self.car = Car()
def produce_engine(self):
self.car.add_part("Sport Engine")
def produce_wheels(self):
self.car.add_part("Sport Wheels")
def produce_body(self):
self.car.add_part("Sport Body")
def get_car(self):
return self.car
# Директор
class Director:
def __init__(self, builder: CarBuilder):
self._builder = builder
def construct_sports_car(self):
self._builder.produce_engine()
self._builder.produce_wheels()
self._builder.produce_body()
# Использование
if __name__ == "__main__":
builder = SportsCarBuilder()
director = Director(builder)
director.construct_sports_car()
car = builder.get_car()
print(f"Car parts: {car.list_parts()}")
Преимущества:
Недостатки:
Паттерн "Построитель" помогает управлять сложностью создания объектов и позволяет создавать различные их представления, делая код более гибким и поддерживаемым.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🤔3❤2
Паттерн Заместитель (Proxy) — это структурный шаблон проектирования, который предоставляет объект, управляющий доступом к другому объекту. Этот паттерн создаёт суррогат или заместителя для другого объекта и контролирует доступ к нему.
Паттерн Заместитель используется в следующих случаях:
Заместитель реализует интерфейс основного объекта и перенаправляет вызовы к реальному объекту, добавляя при этом дополнительную функциональность.
Рассмотрим пример с удалённым заместителем, который управляет доступом к удалённому серверу.
from abc import ABC, abstractmethod
class Subject(ABC):
@abstractmethod
def request(self):
pass
class RealSubject(Subject):
def request(self):
print("Реальный объект: Обработка запроса.")
class Proxy(Subject):
def __init__(self, real_subject):
self._real_subject = real_subject
def request(self):
if self.check_access():
self._real_subject.request()
self.log_access()
def check_access(self):
print("Заместитель: Проверка доступа перед выполнением запроса.")
return True
def log_access(self):
print("Заместитель: Логирование времени запроса.")
# Клиентский код
real_subject = RealSubject()
proxy = Proxy(real_subject)
proxy.request()
В этом примере класс
Proxy
контролирует доступ к классу RealSubject
, добавляя проверку доступа и логирование.Паттерн Заместитель управляет доступом к другому объекту, предоставляя дополнительные возможности, такие как контроль доступа, отложенная инициализация, управление ресурсами, логирование и кэширование.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3❤1
Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. Этот паттерн используется, когда классу заранее неизвестно, объекты каких классов ему нужно создавать, либо он хочет дать возможность своим подклассам выбирать тип создаваемых объектов.
Паттерн включает в себя следующие компоненты:
from abc import ABC, abstractmethod
# Продукт
class Transport(ABC):
@abstractmethod
def deliver(self) -> str:
pass
# Конкретные продукты
class Truck(Transport):
def deliver(self) -> str:
return "Deliver by land in a box."
class Ship(Transport):
def deliver(self) -> str:
return "Deliver by sea in a container."
# Создатель
class Logistics(ABC):
@abstractmethod
def create_transport(self) -> Transport:
pass
def plan_delivery(self) -> str:
transport = self.create_transport()
return transport.deliver()
# Конкретные создатели
class RoadLogistics(Logistics):
def create_transport(self) -> Transport:
return Truck()
class SeaLogistics(Logistics):
def create_transport(self) -> Transport:
return Ship()
# Использование
def client_code(logistics: Logistics):
print(logistics.plan_delivery())
if __name__ == "__main__":
print("App: Launched with the RoadLogistics.")
client_code(RoadLogistics())
print("\nApp: Launched with the SeaLogistics.")
client_code(SeaLogistics())
Преимущества:
Недостатки:
Паттерн "Фабричный метод" позволяет создавать объекты через интерфейс, делегируя создание конкретных объектов подклассам, что делает код более гибким и расширяемым.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
Паттерн "Прототип" (Prototype) — это порождающий паттерн проектирования, который позволяет копировать объекты, не прибегая к их конкретным классам. Он предоставляет механизм для создания новых объектов путем клонирования уже существующих экземпляров-прототипов. Этот паттерн полезен, когда создание объектов требует больших затрат (например, вычислительных или временных), и проще клонировать существующий объект.
Паттерн включает в себя следующие компоненты:
import copy
from abc import ABC, abstractmethod
# Прототип
class Prototype(ABC):
@abstractmethod
def clone(self):
pass
# Конкретный прототип
class ConcretePrototype1(Prototype):
def __init__(self, field):
self.field = field
def clone(self):
return copy.deepcopy(self)
def __str__(self):
return f"ConcretePrototype1 with field: {self.field}"
class ConcretePrototype2(Prototype):
def __init__(self, field):
self.field = field
def clone(self):
return copy.deepcopy(self)
def __str__(self):
return f"ConcretePrototype2 with field: {self.field}"
# Использование
if __name__ == "__main__":
prototype1 = ConcretePrototype1("Value1")
prototype2 = ConcretePrototype2("Value2")
clone1 = prototype1.clone()
clone2 = prototype2.clone()
print(prototype1) # ConcretePrototype1 with field: Value1
print(clone1) # ConcretePrototype1 with field: Value1
print(prototype2) # ConcretePrototype2 with field: Value2
print(clone2) # ConcretePrototype2 with field: Value2
Преимущества:
Недостатки:
Паттерн "Прототип" позволяет быстро и эффективно создавать новые объекты путем клонирования существующих, что упрощает процесс создания сложных объектов и экономит ресурсы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8