Python | Вопросы собесов
13.8K subscribers
35 photos
1 file
959 links
Download Telegram
🤔 Какой метод используется для чтения всего содержимого файла в Python?
Anonymous Quiz
61%
read()
6%
readline()
13%
readall()
20%
readlines()
3💊1
📌 Какие модули для тестирования есть ?

💬 Спросят с вероятностью 3%

Существует множество модулей и библиотек для тестирования, которые помогают автоматизировать процесс тестирования, обнаруживать ошибки и обеспечивать качество кода. Некоторые из наиболее популярных модулей и библиотек для тестирования:

Встроенные модули

1️⃣ unittest

Стандартный модуль для модульного тестирования.

Основан на фреймворке xUnit, что делает его знакомым для многих разработчиков.

Поддерживает создание тестовых классов, тестовых методов, наборов тестов и многое другое.

import unittest

class TestMathOperations(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 1, 2)

if __name__ == '__main__':
unittest.main()


2️⃣ doctest

Позволяет писать тесты прямо в строках документации (docstrings) кода.

Удобен для проверки примеров использования функций.

      def add(a, b):
"""
Возвращает сумму a и b.

>>> add(1, 2)
3
>>> add(-1, 1)
0
"""
return a + b

if name == '__main__':
import doctest
doctest.testmod()


Внешние библиотеки

1️⃣ pytest

Одна из самых популярных библиотек для тестирования в Python.

Поддерживает простой и лаконичный синтаксис тестов.

Поддерживает фикстуры, параметризацию тестов, плагины и многое другое.

      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()


2️⃣ nose2

Наследник библиотеки nose.

Совместим с unittest и расширяет его возможности.

Поддерживает плагины и расширяемость.

      import unittest

class TestMathOperations(unittest.TestCase):
def test_add(self):
self.assertEqual(1 + 1, 2)

if name == '__main__':
import nose2
nose2.main()


3️⃣ hypothesis

Библиотека для проперти-бейсд тестирования (property-based testing).

Генерирует случайные данные для тестов и находит краевые случаи.

      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()


5️⃣ tox

Инструмент для автоматизации тестирования в различных средах.

Полезен для тестирования кода на разных версиях Python и с разными зависимостями.

      [tox]
envlist = py36, py37, py38

[testenv]
deps = pytest
commands = pytest


6️⃣ coverage

Инструмент для измерения покрытия кода тестами.

Генерирует отчеты, показывающие, какие части кода были протестированы, а какие нет.

      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
👍161🔥1
📌 Что такое monkey patch ?

💬 Спросят с вероятностью 3%

Monkey patching — это техника программирования, при которой поведение библиотеки или модуля изменяется во время выполнения программы. Этот метод позволяет динамически изменять или расширять код, написанный другими разработчиками, без изменения исходного кода самой библиотеки или модуля.

Основные особенности:

1️⃣ Динамическое изменение кода: Изменения вносятся в код во время выполнения программы.

2️⃣ Без изменения исходного кода: Оригинальный исходный код библиотеки или модуля не изменяется.

3️⃣ Часто используется для исправления ошибок: 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 может быть полезным, оно также может привести к проблемам, если использовать его неправильно:

1️⃣ Проблемы с отладкой: Динамическое изменение кода может затруднить отладку и понимание программы.

2️⃣ Неожиданное поведение: Изменение поведения стандартных библиотек или модулей может привести к неожиданным результатам в других частях программы.

3️⃣ Нарушение инкапсуляции: Monkey patching нарушает принцип инкапсуляции, так как изменения вносятся в код извне.

Monkey patching — мощная техника, которая позволяет динамически изменять поведение модулей и библиотек во время выполнения программы. Она может быть полезна для исправления ошибок, добавления функциональности или создания фиктивных объектов для тестирования. Однако использовать monkey patching следует осторожно, чтобы избежать проблем с отладкой и неожиданным поведением программы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥31
📌 Как реализовывать тесты ?

💬 Спросят с вероятностью 3%

Реализация тестов — важная часть процесса разработки программного обеспечения, которая помогает обеспечить корректность и надёжность кода. Для написания тестов обычно используется модуль unittest, который является стандартным модулем для тестирования и поставляется вместе. Другие популярные библиотеки для тестирования включают pytest и nose.

Использование модуля unittest

Предоставляет инструменты для создания и выполнения тестов. Давайте рассмотрим основные шаги для написания тестов с использованием unittest.

Основные шаги для написания тестов:

1️⃣ Создание тестового класса: Тестовый класс должен наследоваться от unittest.TestCase.

2️⃣ Написание тестовых методов: Каждый тестовый метод должен начинаться с test_.

3️⃣ Использование методов утверждений: Методы утверждений (assert) используются для проверки условий, таких как assertEqual, assertTrue, assertFalse, assertRaises и другие.

4️⃣ Запуск тестов: Запуск тестов можно осуществить с помощью командной строки или специального вызова внутри скрипта.

Примеры использования:

Допустим, у нас есть простая функция для сложения двух чисел:
# Пример функции в файле 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()


Запуск тестов

Тесты можно запускать разными способами. Вот несколько способов:

1️⃣ Запуск из командной строки:
python -m unittest test_my_module.py


2️⃣ Запуск тестов из файла:

Просто запустите файл 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


Преимущества:

1️⃣ Простой и лаконичный синтаксис: Тесты пишутся проще и читаются легче.

2️⃣ Богатый функционал: Поддержка фикстур, параметризация тестов, расширенные возможности для ассертов.

3️⃣ Множество плагинов: Расширяемость за счет множества доступных плагинов.

Написание тестов — важная часть разработки программного обеспечения, которая помогает обнаруживать ошибки и обеспечивать качество кода. Для тестирования можно использовать стандартный модуль unittest или более мощную библиотеку pytest. Основные шаги включают создание тестовых классов, написание тестовых методов, использование утверждений и запуск тестов. Выбор инструмента зависит от ваших предпочтений и требований проекта, но оба подхода обеспечивают эффективное тестирование вашего кода.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1😁1🎉1
📌 Как еще мы можем гарантировать закрытие файла, если не через with ?

💬 Спросят с вероятностью 3%

Если не использовать конструкцию 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.

Метод enter открывает файл и возвращает его.

Метод exit закрывает файл, обеспечивая его корректное закрытие.

Гарантировать закрытие файла можно несколькими способами, помимо использования конструкции with:

1️⃣ Использовать конструкцию try-finally, чтобы файл всегда закрывался независимо от возникновения исключений.

2️⃣ Использовать модуль contextlib и его утилиту closing для автоматического закрытия файла.

3️⃣ Создать пользовательский контекстный менеджер, реализовав методы enter и exit.

Эти методы обеспечивают надёжное управление ресурсами и предотвращают утечки ресурсов, которые могут возникнуть при некорректном закрытии файлов.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82🔥1
🤔 Что произойдет, если в Python вызвать функцию, использующую yield, но не пройти по итератору?
Anonymous Quiz
10%
возникнет исключение
16%
вернется None
24%
функция завершится без результата
50%
создастся генератор
📌 Как Python взаимодействует с файлом ?

💬 Спросят с вероятностью 3%

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
👍152🔥2
📌 Что известно о принципе SLAP ?

💬 Спросят с вероятностью 3%

Принцип 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)


🤔 Почему это важно?

1️⃣ Упрощение понимания кода: Легче читать и понимать, когда каждая функция выполняет только одну задачу.

2️⃣ Легкость тестирования: Отдельные функции проще тестировать.

3️⃣ Поддерживаемость: Изменения в одной части программы менее вероятно вызовут ошибки в другой.

Принцип SLAP означает, что каждая функция должна выполнять задачи только на одном уровне абстракции. Это делает код более чистым и легким для понимания.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92🔥1
🤔 Что произойдет, если в Python изменить ключ в dict во время итерации по нему?
Anonymous Quiz
17%
ничего не произойдет
17%
возникнет ошибка компиляции
23%
возникнет исключение RuntimeError
43%
значение ключа изменится
👍11😁2
📌 Что такое code cohesion & code coupling ?

💬 Спросят с вероятностью 3%

Кодовые метрики когезии (cohesion) и связи (coupling) играют ключевую роль в проектировании программного обеспечения. Давайте разберем их более подробно.

Когезия (Cohesion)

Это мера того, насколько сильно элементы внутри модуля связаны друг с другом. Высокая когезия означает, что элементы модуля работают вместе для выполнения одной задачи.

🤔 Почему это важно:

1️⃣ Понятность: Высокая когезия делает модули более понятными и логичными, так как они выполняют четко определенную функцию.

2️⃣ Поддерживаемость: Модули с высокой когезией легче модифицировать, тестировать и отлаживать, поскольку изменения в одном модуле менее вероятно повлияют на другие.

3️⃣ Повторное использование: Высококогезионные модули могут быть легче повторно использованы в других частях программы или в других проектах.

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)

Это мера зависимости между модулями. Низкая связь означает, что изменения в одном модуле минимально влияют на другие модули.

🤔 Почему это важно:

1️⃣ Изоляция изменений: Модули с низкой связью менее зависимы друг от друга, что упрощает внесение изменений и улучшений в код.

2️⃣ Тестируемость: Легче тестировать модули с низкой связью, так как они меньше зависят от других частей системы.

3️⃣ Повторное использование: Модули с низкой связью можно легче интегрировать в другие системы.

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🔥21
🤔 Какое значение имеет неинициализированная переменная в Python?
Anonymous Quiz
36%
None
17%
undefined
6%
null
41%
невозможно использовать неинициализированные переменные
📌 Что такое порождающий паттерн ?

💬 Спросят с вероятностью 3%

Порождающий паттерн (creational pattern) — это тип шаблонов проектирования, который предоставляет различные способы создания объектов, помогая отделить логику создания объектов от их основного использования. Порождающие паттерны помогают сделать систему более гибкой и независимой от конкретных классов, которые она использует.

🤔 Основные порождающие паттерны

1️⃣ Singleton (Одиночка)

Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру.
      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


2️⃣ Factory Method (Фабричный метод)

Определяет интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов.
      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
👍81🎉1
🤔 Какой модуль в стандартной библиотеке Python используется для работы с выражениями XPath?
Anonymous Quiz
24%
xml.dom
10%
xml.sax
33%
xml.etree.ElementTree
33%
re
👾51
Forwarded from Идущий к IT
10$ за техническое собеседование на английском языке:

1. Отправьте запись технического собеседования на английском языке файлом на этот аккаунт
2. Добавьте ссылку на вакансию или пришлите название компании и должность
3. Напишите номер кошелка USDT (Tether) на который отправить 10$

🛡 Важно:

– Запись будет использована только для сбора данных о вопросах
– Вы останетесь анонимны
– Запись нигде не будет опубликована

🤝 Условия:

– Внятный звук, различимая речь
– Допустимые профессии:
• Любые программисты
• DevOps
• Тестировщики
• Дата сайнтисты
• Бизнес/Системные аналитики
• Прожекты/Продукты
• UX/UI и продукт дизайнеры
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4👀1
📌 Что такое абстрактная фабрика ?

💬 Спросят с вероятностью 3%

Абстрактная фабрика (Abstract Factory) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов. Этот паттерн используется, когда система должна быть независимой от способа создания, композиции и представления своих продуктов.

🤔 Зачем она нужна?

1️⃣ Изоляция конкретных классов: Клиентский код работает с интерфейсами, что позволяет легко менять классы продуктов без изменения самого кода.

2️⃣ Семейства продуктов: Обеспечивает создание семейств связанных объектов, гарантируя их совместимость друг с другом.

3️⃣ Упрощение тестирования: Использование интерфейсов и абстрактных классов облегчает написание тестов и создание заглушек для модульного тестирования.

🤔 Как она работает?

Определяет интерфейсы для создания абстрактных продуктов. Конкретные фабрики реализуют эти интерфейсы, создавая конкретные продукты.

Рассмотрим пример абстрактной фабрики для создания семейств продуктов 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())


Преимущества:

1️⃣ Изоляция конкретных классов: Упрощает замену продуктовых семейств.

2️⃣ Согласованность продуктов: Обеспечивает совместимость создаваемых продуктов.

3️⃣ Легкость тестирования: Интерфейсы и абстрактные классы упрощают создание тестов.

Недостатки:

1️⃣ Сложность кода: Добавление большого количества классов и интерфейсов может усложнить структуру кода.

2️⃣ Увеличение количества кода: Необходимость создания множества подклассов.

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

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53
📌 Что такое Построитель (Builder) ?

💬 Спросят с вероятностью 3%

Паттерн "Построитель" (Builder) — это порождающий паттерн проектирования, который позволяет создавать сложные объекты поэтапно. В отличие от других порождающих паттернов, Builder предоставляет возможность постепенно конструировать объект, контролируя процесс его создания на каждом этапе. Этот паттерн особенно полезен, когда нужно создать объект с различными конфигурациями или когда создание объекта требует много шагов.

🤔 Зачем нужен данный паттерн?

1️⃣ Управление сложностью создания объектов: Позволяет разбить процесс создания сложных объектов на более простые шаги.

2️⃣ Гибкость в создании объектов: Упрощает создание различных представлений объекта.

3️⃣ Читаемость и поддерживаемость: Делает код более читаемым и поддерживаемым за счет разделения процесса создания объекта на отдельные методы.

🤔 Как работает данный паттерн?

Паттерн состоит из следующих компонентов:

Builder: Интерфейс, определяющий методы для поэтапного создания объекта.

Concrete Builder: Конкретная реализация интерфейса Builder, создающая и собирающая части конечного продукта.

Product: Объект, который необходимо создать.

Director: Опциональный компонент, управляющий процессом создания объекта с использованием интерфейса 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()}")


Преимущества:

1️⃣ Разделение сложного конструктора на простые шаги: Каждый метод отвечает за создание определенной части продукта.

2️⃣ Поддержка различных представлений объекта: Можно использовать один и тот же процесс создания для создания различных вариаций продукта.

3️⃣ Улучшенная читаемость и поддерживаемость: Код легче понимать и изменять.

Недостатки:

1️⃣Усложнение структуры кода: Добавление новых классов и методов может усложнить проект.

2️⃣Необходимость в дополнительном коде: Требуется больше кода для реализации паттерна, особенно при создании новых конкретных построителей и продуктов.

Паттерн "Построитель" помогает управлять сложностью создания объектов и позволяет создавать различные их представления, делая код более гибким и поддерживаемым.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🤔32
📌 Что такое паттерн Заместитель (Proxy)?

💬 Спрашивают в 3% собеседований

Паттерн Заместитель (Proxy) — это структурный шаблон проектирования, который предоставляет объект, управляющий доступом к другому объекту. Этот паттерн создаёт суррогат или заместителя для другого объекта и контролирует доступ к нему.

🤔 Зачем нужен паттерн Заместитель

Паттерн Заместитель используется в следующих случаях:

1️⃣ Управление доступом: Когда необходимо контролировать доступ к ресурсу.

2️⃣ Отложенная инициализация: Когда необходимо отложить создание ресурсоёмких объектов до момента их первого использования.

3️⃣ Управление ресурсами: Для управления ресурсами, такими как память или сетевые соединения.

4️⃣ Логирование и кэширование: Для добавления дополнительной функциональности, такой как логирование или кэширование, без изменения кода основного объекта.

🤔 Типы заместителей

1️⃣ Управляющий заместитель (Virtual Proxy): Контролирует доступ к объекту, создавая его по требованию.

2️⃣ Защитный заместитель (Protection Proxy): Контролирует доступ к объекту, ограничивая права пользователей.

3️⃣ Удалённый заместитель (Remote Proxy): Управляет доступом к объекту, находящемуся в другом адресном пространстве.

4️⃣ Кэш-прокси (Cache 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🔥31
📌 Что такое Фабричный метод (Factory method) ?

💬 Спросят с вероятностью 3%

Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. Этот паттерн используется, когда классу заранее неизвестно, объекты каких классов ему нужно создавать, либо он хочет дать возможность своим подклассам выбирать тип создаваемых объектов.

🤔 Зачем нужен данный паттерн?

1️⃣ Изоляция создания объектов: Позволяет суперклассу делегировать создание объектов подклассам, изолируя логику создания объектов от основной логики программы.

2️⃣ Расширяемость: Упрощает добавление новых типов объектов, не изменяя существующий код.

3️⃣ Упрощение тестирования: Легче тестировать классы, так как создание объектов сосредоточено в одном месте.

🤔Как работает данный паттерн?

Паттерн включает в себя следующие компоненты:

Продукт (Product): Интерфейс или абстрактный класс для объектов, которые будут создаваться.

Конкретный продукт (ConcreteProduct): Конкретные реализации продукта.

Создатель (Creator): Абстрактный класс или интерфейс с объявлением фабричного метода.

Конкретный создатель (ConcreteCreator): Классы, которые реализуют фабричный метод для создания конкретных продуктов.

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())


Преимущества:

1️⃣ Изоляция создания объектов: Создание объектов делегируется подклассам, что изолирует основной код от логики создания объектов.

2️⃣ Расширяемость: Легко добавлять новые продукты, не изменяя существующий код.

3️⃣ Упрощение тестирования: Легко подменять конкретные реализации продуктов для тестирования.

Недостатки:

1️⃣ Усложнение кода: Требует создания большого количества дополнительных классов.

2️⃣ Поддержка иерархии классов: Может усложнить систему, если классы продуктов и создателей становятся слишком сложными.

Паттерн "Фабричный метод" позволяет создавать объекты через интерфейс, делегируя создание конкретных объектов подклассам, что делает код более гибким и расширяемым.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
📌 Что такое паттерн Прототип (Prototype) ?

💬 Спросят с вероятностью 3%

Паттерн "Прототип" (Prototype) — это порождающий паттерн проектирования, который позволяет копировать объекты, не прибегая к их конкретным классам. Он предоставляет механизм для создания новых объектов путем клонирования уже существующих экземпляров-прототипов. Этот паттерн полезен, когда создание объектов требует больших затрат (например, вычислительных или временных), и проще клонировать существующий объект.

🤔 Зачем нужен данный паттерн?

1️⃣ Экономия ресурсов: Избегает затрат на создание нового объекта с нуля, используя существующий объект как шаблон.

2️⃣ Изоляция клиентов от классов продуктов: Позволяет создавать новые объекты без привязки к конкретным классам, что повышает гибкость системы.

3️⃣ Упрощение процесса создания сложных объектов: Легко создавать объекты со сложной конфигурацией, клонируя уже настроенные экземпляры.

🤔 Как работает данный паттерн?

Паттерн включает в себя следующие компоненты:

Прототип (Prototype): Интерфейс с методом клонирования, который будет реализован конкретными классами.

Конкретный прототип (ConcretePrototype): Классы, которые реализуют метод клонирования для создания копий своих объектов.

Клиент (Client): Использует метод клонирования для создания новых объектов.

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


Преимущества:

1️⃣ Экономия ресурсов: Быстрое создание новых объектов путем клонирования.

2️⃣ Гибкость: Легко создавать объекты без привязки к конкретным классам.

3️⃣ Упрощение создания сложных объектов: Позволяет клонировать уже настроенные объекты.

Недостатки:

1️⃣ Сложность реализации клонирования: Необходимо правильно реализовать глубокое или поверхностное копирование, что может быть сложно.

2️⃣ Проблемы с копированием объектов: Некоторые объекты могут содержать ссылки на другие, что требует сложных механизмов для правильного клонирования.

Паттерн "Прототип" позволяет быстро и эффективно создавать новые объекты путем клонирования существующих, что упрощает процесс создания сложных объектов и экономит ресурсы.

🔥 ТОП ВОПРОСОВ С СОБЕСОВ

🔒 База собесов | 🔒 База тестовых
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8