❤5👍4👾1
pytest
— это популярный и мощный фреймворк для тестирования, который позволяет писать компактные и легко читаемые тесты. Он широко используется благодаря своей простоте, гибкости и поддержке различных расширений. Поддерживает как модульное, так и функциональное тестирование, предоставляя множество удобных инструментов для тестирования кода.Основные особенности
unittest
и другими фреймворками, что упрощает миграцию.Установка
pytest
Можно установить с помощью pip:
pip install pytest
Тестирование функции
Предположим, у нас есть простая функция для сложения двух чисел:
# math_operations.py
def add(a, b):
return a + b
Теперь напишем тест для этой функции с его использованием:
# test_math_operations.py
from math_operations import add
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(-1, -1) == -2
Запуск тестов
Для него можно использовать команду
pytest
:pytest test_math_operations.py
pytest
автоматически найдет и выполнит все тесты, а затем выведет результаты на экран.Фикстуры (fixtures)
Позволяют задавать инициализацию, необходимую для тестов. Они могут использоваться для подготовки данных, создания объектов и других операций, которые нужны перед выполнением тестов.
# test_math_operations.py
import pytest
from math_operations import add
@pytest.fixture
def input_data():
return 1, 2
def test_add(input_data):
a, b = input_data
assert add(a, b) == 3
Параметризация тестов
Позволяет запускать один и тот же тест с разными наборами данных.
# test_math_operations.py
import pytest
from math_operations import add
@pytest.mark.parametrize("a, b, expected", [
(1, 2, 3),
(-1, 1, 0),
(-1, -1, -2),
])
def test_add(a, b, expected):
assert add(a, b) == expected
Плагины:
Поддерживает множество плагинов, которые расширяют его функциональность. Некоторые из популярных плагинов:
unittest.mock
для создания и управления mock-объектами.Пример использования плагина
pytest-cov
Для его установки:
pip install pytest-cov
Запуск тестов с генерацией отчета о покрытии:
pytest --cov=my_module test_my_module.py
pytest
— это мощный и гибкий фреймворк для тестирования, который упрощает написание и выполнение тестов. Благодаря простому синтаксису, поддержке фикстур, параметризации и плагинов, Позволяет эффективно автоматизировать процесс тестирования и обеспечивать высокое качество кода.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤2🔥1
Юнит-тестирование (unit testing) — это метод тестирования ПО, при котором отдельные модули или компоненты (юниты) программы проверяются на корректность их работы. Предназначены для проверки небольших, изолированных частей кода, таких как функции или методы классов, чтобы убедиться, что они работают правильно.
Особенности:
Преимущества:
Пример использования
unittest
Он является встроенным и предоставляет богатые возможности для написания и выполнения юнит-тестов.
Пример кода для юнит-тестирования:
Предположим, у нас есть модуль
math_operations.py
с функцией add
:# math_operations.py
def add(a, b):
return a + b
Теперь тест для этой функции:
# test_math_operations.py
import unittest
from math_operations import add
class TestMathOperations(unittest.TestCase):
def test_add(self):
self.assertEqual(add(1, 2), 3)
self.assertEqual(add(-1, 1), 0)
self.assertEqual(add(-1, -1), -2)
if __name__ == '__main__':
unittest.main()
Запуск тестов
Для него можно выполнить скрипт
test_math_operations.py
:python test_math_operations.py
Или использовать команду
unittest
из командной строки:python -m unittest test_math_operations.py
Использование
pytest
для юнит-тестированияПредлагает более лаконичный и мощный подход к юнит-тестированию.
# test_math_operations.py
from math_operations import add
def test_add():
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(-1, -1) == -2
Запуск тестов с
pytest
Убедитесь, что он установлен. Вы можете установить его с помощью pip:
pip install pytest
Запуск тестов:
pytest test_math_operations.py
Юнит-тестирование — это важный метод тестирования, который помогает обеспечивать качество и надежность кода, проверяя отдельные модули или компоненты программы. Использование таких инструментов, как
unittest
и pytest
, позволяет автоматизировать процесс тестирования, выявлять ошибки на ранних стадиях разработки и уверенно вносить изменения в код.Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥2❤1😁1
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