В асинхронном коде выполнение задач происходит не в линейном порядке, а в зависимости от готовности событий. Здесь линеаризация может привести к потере преимуществ асинхронности.
import asyncio
async def fetch_data():
await asyncio.sleep(1)
return "Data fetched"
async def main():
data = await fetch_data()
print(data)
asyncio.run(main())
Рекурсивные алгоритмы, такие как обход дерева или вычисление факториала, невозможно представить в виде линейного кода без потери логики и структуры.
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
В некоторых случаях требуется обработка ошибок и исключений, что нарушает линейную структуру кода.
try:
result = 10 / 0
except ZeroDivisionError:
print("Деление на ноль!")
Когда код содержит сложные вложенные циклы и условия, его линейное представление становится громоздким и трудночитаемым.
for i in range(10):
for j in range(10):
if i == j:
print(f"{i} равно {j}")
Некоторые паттерны проектирования, такие как фабричный метод или стратегия, предполагают использование классов и объектов, что не всегда удобно линеаризовать.
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof"
class Cat(Animal):
def speak(self):
return "Meow"
animals = [Dog(), Cat()]
for animal in animals:
print(animal.speak())
Параллельные вычисления, где задачи выполняются одновременно в разных потоках или процессах, не могут быть линеаризованы.
import threading
def print_numbers():
for i in range(5):
print(i)
thread = threading.Thread(target=print_numbers)
thread.start()
thread.join()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Инкапсуляция предполагает скрытие внутреннего состояния объекта от внешнего мира. Это достигается с помощью модификаторов доступа, таких как private, protected и public. В Python используются соглашения об именовании (например, одиночное подчеркивание
_
для "protected" и двойное подчеркивание __
для "private") для индикации уровня доступа.Инкапсуляция позволяет контролировать доступ к данным и методам объекта. Это предотвращает некорректное использование или изменение состояния объекта, что может привести к ошибкам.
Инкапсуляция способствует созданию четких интерфейсов для взаимодействия с объектами. Внешний код взаимодействует с объектом через его публичные методы, не зная о внутреннем устройстве.
Инкапсуляция помогает разделять функциональность на независимые модули. Это облегчает разработку, тестирование и сопровождение кода.
В этом примере переменная
__balance
скрыта от внешнего доступа. Методы deposit
, withdraw
и get_balance
обеспечивают контролируемый доступ к этой переменной, обеспечивая инкапсуляцию.class BankAccount:
def __init__(self, initial_balance):
self.__balance = initial_balance # Закрытая переменная
def deposit(self, amount):
if amount > 0:
self.__balance += amount
else:
raise ValueError("Amount must be positive")
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
else:
raise ValueError("Invalid withdrawal amount")
def get_balance(self):
return self.__balance
# Создание объекта и взаимодействие с ним
account = BankAccount(100)
account.deposit(50)
print(account.get_balance()) # 150
account.withdraw(30)
print(account.get_balance()) # 120
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Они нужны для того, чтобы определять поведение объектов в различных ситуациях и обеспечивать взаимодействие с базовыми механизмами языка.
Метод
__init__
используется для инициализации новых объектов. Он позволяет задавать начальные значения атрибутов объекта. class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("Alice", 30)
Метод
__str__
определяет, как объект будет представлен в виде строки. Это удобно для пользовательского вывода. class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name}, {self.age} years old"
person = Person("Alice", 30)
print(person) # Alice, 30 years old
Dunder методы позволяют перегружать стандартные операторы. Например,
__add__
позволяет определить поведение оператора +
для объектов класса. class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(5, 7)
v3 = v1 + v2
print(v3) # Vector(7, 10)
Метод
__getitem__
позволяет определить, как объект класса будет вести себя при доступе к его элементам по индексу. class CustomList:
def __init__(self, elements):
self.elements = elements
def __getitem__(self, index):
return self.elements[index]
clist = CustomList([1, 2, 3, 4, 5])
print(clist[2]) # 3
Метод
__enter__
и __exit__
позволяют создавать объекты, которые могут использоваться в контекстах with
. class ManagedFile:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
with ManagedFile('example.txt') as f:
content = f.read()
print(content)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Являются специальными методами, которые позволяют классам взаимодействовать с встроенными функциями
len()
и abs()
соответственно. Эти методы помогают сделать пользовательские объекты более интуитивно понятными и удобными для использования.Используется для определения длины объекта. Он должен возвращать количество элементов в объекте или какую-то другую числовую характеристику длины объекта. Например, для списков, кортежей и строк метод
__len__
возвращает количество элементов или символов.class MyCollection:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
collection = MyCollection([1, 2, 3, 4, 5])
print(len(collection)) # Вывод: 5
Метод
__abs__
используется для определения абсолютного значения объекта. Он должен возвращать абсолютное значение объекта, как это делает встроенная функция abs()
для чисел.class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __abs__(self):
return (self.x**2 + self.y**2) ** 0.5
vector = Vector(3, 4)
print(abs(vector)) # Вывод: 5.0
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это специальный метод, который вызывается автоматически при создании нового объекта класса. Этот метод называется
__init__()
. Он используется для инициализации объекта, то есть задания начальных значений атрибутов объекта.Необходимо определить метод
__init__()
внутри класса. class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def display_info(self):
print(f"Name: {self.name}, Age: {self.age}")
Включает вызов конструктора. Для этого используется имя класса, за которым следуют круглые скобки с аргументами, передаваемыми в конструктор.
person1 = Person("Alice", 30)
person1.display_info()
Кроме конструктора, классы могут иметь и другие методы для выполнения различных операций.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
# Создание объекта
rect1 = Rectangle(10, 5)
print(f"Area: {rect1.area()}") # Вывод: Area: 50
print(f"Perimeter: {rect1.perimeter()}") # Вывод: Perimeter: 30
Класс
Rectangle
имеет конструктор, который инициализирует атрибуты width
и height
. Методы area()
и perimeter()
вычисляют и возвращают площадь и периметр прямоугольника соответственно.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это способность программы исследовать и изменять свою структуру и поведение во время выполнения. Рефлексия позволяет получить информацию о типах данных, структурах, объектах и их атрибутах динамически, то есть в процессе выполнения программы.
Определение типа объекта и его структуры во время выполнения.
Создание экземпляров классов и вызов их методов без явного указания имен классов и методов в коде.
Доступ к атрибутам и методам объектов, их изменение и вызов.
x = [1, 2, 3]
print(type(x)) # <class 'list'>
print(dir(x)) # Выводит все методы и атрибуты объекта списка
class MyClass:
def __init__(self, value):
self.value = value
def my_method(self):
return "Hello, world!"
obj = MyClass(10)
# Проверка наличия атрибута
print(hasattr(obj, 'value')) # True
# Получение значения атрибута
print(getattr(obj, 'value')) # 10
# Установка значения атрибута
setattr(obj, 'value', 20)
print(getattr(obj, 'value')) # 20
# Проверка наличия метода
print(hasattr(obj, 'my_method')) # True
# Вызов метода
method = getattr(obj, 'my_method')
print(method()) # Hello, world!
class MyClass:
def __init__(self, value):
self.value = value
def my_method(self):
return f"Value is {self.value}"
# Динамическое создание объекта
klass = globals()['MyClass']
obj = klass(42)
# Динамический вызов метода
method = getattr(obj, 'my_method')
print(method()) # Value is 42
inspect
import inspect
def my_function(param1, param2):
pass
# Получение информации о параметрах функции
signature = inspect.signature(my_function)
for param in signature.parameters.values():
print(param.name, param.default, param.annotation)
# Получение всех методов класса
class MyClass:
def method(self):
pass
methods = inspect.getmembers(MyClass, predicate=inspect.isfunction)
print(methods) # [('method', <function MyClass.method at 0x...>)]
Позволяет писать более общие и гибкие функции, которые могут работать с различными типами данных.
Облегчает отладку и тестирование кода, предоставляя средства для анализа объектов и их состояния.
Позволяет адаптировать поведение программы во время выполнения в зависимости от контекста и условий.
Может сделать код более сложным для понимания и сопровождения.
Рефлексия может повлиять на производительность, особенно при частом использовании в критически важных участках кода.
Использование рефлексии может открыть доступ к внутренним частям объектов, что может быть потенциально опасным при неправильном использовании.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это специальный метод, который вызывается автоматически, когда объект класса уничтожается. В Python этот метод называется
__del__()
. Деструктор используется для выполнения операций очистки, таких как освобождение ресурсов или выполнение завершающих действий перед тем, как объект будет удален из памяти.Определяется внутри класса с помощью метода
__del__()
. class FileManager:
def __init__(self, filename):
self.file = open(filename, 'w')
print(f"Файл {filename} открыт для записи.")
def write_data(self, data):
self.file.write(data)
def __del__(self):
self.file.close()
print("Файл закрыт.")
FileManager
имеет конструктор __init__()
, который открывает файл для записи.write_data()
записывает данные в файл.__del__()
закрывает файл, когда объект FileManager
уничтожается.Когда объект класса создается, вызывается конструктор. Когда объект больше не нужен, вызывается деструктор:
manager = FileManager('example.txt')
manager.write_data('Hello, world!')
# Когда объект manager больше не нужен, вызывается деструктор и файл закрывается
Python использует механизм сборки мусора для автоматического управления памятью. Когда объект больше не используется (например, нет активных ссылок на него), сборщик мусора удаляет объект и вызывает его деструктор.
Точное время вызова деструктора зависит от работы сборщика мусора. Это означает, что нельзя гарантировать момент вызова деструктора. Поэтому для критических операций лучше использовать явное управление ресурсами, например, с помощью контекстных менеджеров (
with
).Для явного управления ресурсами и их освобождения в предсказуемый момент лучше использовать контекстные менеджеры.
with open('example.txt', 'w') as file:
file.write('Hello, world!')
# Файл автоматически закрывается после выхода из блока with
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
REST (Representational State Transfer) — это архитектурный стиль для разработки веб-сервисов, который использует стандартные методы HTTP для взаимодействия между клиентом и сервером. В REST каждая операция выполняется с использованием определённого HTTP-метода: GET для получения данных, POST для создания, PUT для обновления и DELETE для удаления. RESTful API использует унифицированные ресурсы и URL для представления данных, а также статeless-коммуникацию между клиентом и сервером. Основной принцип REST — это простота и масштабируемость.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Используется модуль
abc
(Abstract Base Classes). Абстрактный класс не может быть инстанцирован и предназначен для создания шаблонов, которые должны быть реализованы в подклассах. Для использования абстрактных классов и методов нужно импортировать модуль
abc
.Абстрактный класс должен наследоваться от
ABC
(абстрактный базовый класс), который предоставляется модулем abc
.Абстрактные методы обозначаются декоратором
@abstractmethod
. Эти методы должны быть реализованы в подклассах, иначе они тоже станут абстрактными.from abc import ABC, abstractmethod
# Создание абстрактного класса
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass
@abstractmethod
def move(self):
pass
# Попытка создания экземпляра абстрактного класса приведет к ошибке
# animal = Animal() # TypeError: Can't instantiate abstract class Animal with abstract methods make_sound, move
# Создание подклассов, которые реализуют абстрактные методы
class Dog(Animal):
def make_sound(self):
return "Woof"
def move(self):
return "Runs"
class Bird(Animal):
def make_sound(self):
return "Tweet"
def move(self):
return "Flies"
# Теперь можно создать экземпляры подклассов
dog = Dog()
print(dog.make_sound()) # Woof
print(dog.move()) # Runs
bird = Bird()
print(bird.make_sound()) # Tweet
print(bird.move()) # Flies
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Обычные методы работают с экземплярами класса и могут изменять их состояние. Они принимают первым аргументом ссылку на сам экземпляр (
self
).class Dog:
def __init__(self, name):
self.name = name # Атрибут объекта
def bark(self):
return f"{self.name} says woof!"
dog = Dog("Buddy")
print(dog.bark()) # Buddy says woof!
Методы класса работают с самим классом, а не с экземплярами. Они принимают первым аргументом ссылку на класс (
cls
). Для создания метода класса используется декоратор @classmethod
.class Dog:
species = "Canis lupus familiaris" # Атрибут класса
@classmethod
def get_species(cls):
return cls.species
print(Dog.get_species()) # Canis lupus familiaris
Статические методы не зависят ни от экземпляра класса, ни от самого класса. Они не получают автоматически ни ссылку на экземпляр (
self
), ни ссылку на класс (cls
). Для создания статического метода используется декоратор @staticmethod
.class Dog:
@staticmethod
def is_domesticated():
return True
print(Dog.is_domesticated()) # True
Магические методы (или dunder методы, от "double underscore") определяют специальные поведения объектов, такие как инициализация, строковое представление, перегрузка операторов и другие. Они имеют двойное подчеркивание в начале и в конце имени.
Некоторые распространенные магические методы:
__init__
: Инициализация объекта.__str__
: Строковое представление объекта.__repr__
: Официальное строковое представление объекта, используемое для отладки.__len__
: Определяет длину объекта.__add__
: Перегружает оператор сложения.class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old"
dog = Dog("Buddy", 2)
print(dog) # Buddy is 2 years old
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Юнит-тесты проверяют отдельные модули или функции на правильность их работы. Эти тесты изолированы и проверяют минимальные функциональные блоки программы.
import unittest
def add(a, b):
return a + b
class TestAddFunction(unittest.TestCase):
def test_add_positive_numbers(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative_numbers(self):
self.assertEqual(add(-1, -1), -2)
if __name__ == '__main__':
unittest.main()
Интеграционные тесты проверяют взаимодействие между различными модулями или компонентами системы, чтобы убедиться, что они работают вместе правильно.
import unittest
class Database:
def connect(self):
return "Connected to database"
class Application:
def __init__(self):
self.db = Database()
def start(self):
return self.db.connect()
class TestApplication(unittest.TestCase):
def test_application_start(self):
app = Application()
self.assertEqual(app.start(), "Connected to database")
if __name__ == '__main__':
unittest.main()
Функциональные тесты проверяют конкретные функции и их соответствие требованиям. Эти тесты обычно основаны на спецификациях и проверяют, правильно ли выполняется функция.
def login(username, password):
if username == "admin" and password == "secret":
return "Login successful"
else:
return "Login failed"
class TestLoginFunction(unittest.TestCase):
def test_valid_login(self):
self.assertEqual(login("admin", "secret"), "Login successful")
def test_invalid_login(self):
self.assertEqual(login("user", "password"), "Login failed")
if __name__ == '__main__':
unittest.main()
Системные тесты проверяют всю систему в целом, проверяя все компоненты и функции вместе в интегрированной среде.
class SystemTest(unittest.TestCase):
def test_system(self):
app = Application()
result = app.start()
self.assertEqual(result, "Connected to database")
self.assertEqual(login("admin", "secret"), "Login successful")
if __name__ == '__main__':
unittest.main()
Приемочные тесты проверяют систему на соответствие бизнес-требованиям и ожиданиям пользователя. Эти тесты часто проводятся пользователями или командой контроля качества.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM