Anonymous Quiz
10%
Магические методы вызываются напрямую пользователем
23%
Магические методы всегда должны быть приватными
49%
Магические методы используются для перегрузки операторов и встроенных функций
18%
Магические методы не могут быть переопределены
👍2🔥1
Генератор в Python – это специальный тип функций, который позволяет вам возвращать значение и позже продолжить выполнение функции с того места, где она была остановлена. Это достигается с помощью ключевого слова
yield
.Главное отличие генератора от обычной функции заключается в том, что генератор возвращает итерируемый объект, через который можно пройти только один раз. Это позволяет эффективно работать с данными, не загружая полностью их в память. Это особенно полезно, когда вам нужно работать с большими объемами данных или когда вы не знаете заранее, сколько элементов вам понадобится.
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
counter = count_up_to(5)
for num in counter:
print(num)
В этом примере функция
count_up_to
является генератором. Когда вы вызываете её, она не выполняет свой код сразу. Вместо этого, она возвращает итерируемый объект. Когда вы итерируетесь через этот объект (например, используя цикл for
), код внутри функции выполняется до первого yield
. Значение, которое следует за yield
, возвращается в цикл. При следующей итерации выполнение функции возобновляется сразу после yield
и продолжается до следующего yield
.Использование генераторов позволяет сэкономить ресурсы, так как значения генерируются по мере необходимости, а не хранятся в памяти.
В асинхронных функциях (
async def
) используется await
вместо yield
, но концептуально это очень похоже. Когда функция достигает await
, она возвращает управление вызывающей стороне, позволяя другим задачам выполняться, пока текущая задача находится в ожидании (например, ожидает ответа от сервера).import asyncio
async def fetch_data():
print('Start fetching')
await asyncio.sleep(2) # Имитация асинхронной задачи, например, запроса к серверу
print('Done fetching')
return {'data': 1}
async def main():
print('Before fetching')
result = await fetch_data()
print('Result:', result)
print('After fetching')
asyncio.run(main())
Здесь
fetch_data
является асинхронной функцией. Когда она достигает строки await asyncio.sleep(2)
, управление возвращается в main
, позволяя выполнять другие операции, в то время как fetch_data
находится в ожидании.Таким образом, генераторы и асинхронные функции позволяют Python более эффективно использовать однопоточную модель исполнения, предоставляя механизм для конкурентного выполнения задач, особенно в ситуациях, когда много времени уходит на ожидание ввода/вывода.
Генератор в Python - это инструмент для создания итератора, который можно перебирать (итерировать) один раз. Генераторы используются для более эффективной работы с данными, позволяя не загружать все данные в память сразу.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍8🔥1
Anonymous Quiz
12%
Сборка мусора работает только с типами данных, встроенными в Python
6%
Сборка мусора удаляет объекты сразу после их создания
3%
Сборка мусора выполняется вручную пользователем
78%
Сборка мусора основана на подсчете ссылок и сборке циклических ссылок
Индексы – это специальные структуры данных, которые используются для ускорения операций выборки (retrieval) и поиска данных в таблице. Они подобны индексам в книге: вместо того, чтобы перелистывать всю книгу (или всю таблицу данных) для поиска нужной информации, вы можете использовать индекс для быстрого нахождения необходимых данных.
Индексы существенно ускоряют поиск и выборку данных, особенно в больших таблицах. Без индексов база данных должна была бы осуществлять "полное сканирование таблицы" (full table scan), что очень ресурсоемко и медленно, особенно для больших объемов данных. Однако стоит учитывать, что создание и поддержание индексов также требует дополнительных ресурсов, включая место на диске и время на обновление индекса при изменении данных в таблице.
Существуют различные типы индексов, и они могут быть реализованы по-разному в зависимости от системы управления базами данных (СУБД), но обычно они используют структуры данных, такие как B-деревья или хеш-таблицы, для эффективного хранения и поиска данных.
Например, если вы создаете индекс для столбца "Фамилия" в таблице с записями сотрудников, СУБД создаст структуру данных (например, B-дерево), которая позволит быстро находить записи по значению фамилии, не перебирая каждую запись в таблице.
CREATE INDEX idx_lastname ON employees (lastname);
Эта SQL-команда создает индекс
idx_lastname
для столбца lastname
в таблице employees
. После создания этого индекса запросы, которые ищут сотрудников по фамилии, будут выполняться значительно быстрее.Индексы – это структуры, которые ускоряют поиск данных в таблицах, работая подобно индексам в книге. Они особенно полезны для больших таблиц и сложных запросов.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍5💊2❤1
Anonymous Quiz
13%
threading.local()
11%
contextvars.ContextVar()
26%
asynccontext.local()
50%
asyncio.Local()
💊12
Принципы объектно-ориентированного программирования (ООП) – это фундаментальные концепции, лежащие в основе этого стиля программирования. Они помогают программистам создавать гибкий и масштабируемый код. Всего 4 принципа:
Это принцип, согласно которому детали реализации класса скрыты от внешнего использования. Это позволяет изменять внутреннее устройство класса без влияния на другие части программы. В Python инкапсуляция достигается за счет использования публичных, защищенных (
_имя
) и приватных (__имя
) методов и атрибутов.class Account:
def __init__(self):
self.__balance = 0 # Приватный атрибут
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
Здесь детали реализации учета баланса скрыты от пользователя.
Позволяет создавать новые классы на основе уже существующих, наследуя их свойства и методы. Это облегчает повторное использование кода и упрощает расширение функциональности.
class SavingsAccount(Account): # Наследование от класса Account
def __init__(self):
super().__init__()
self.interest_rate = 0.05
def add_interest(self):
self.deposit(self.get_balance() * self.interest_rate)
Класс
SavingsAccount
расширяет функционал Account
, добавляя начисление процентов.Это способность объектов использовать методы производных классов, даже если они вызываются с точки зрения их базового класса. Это позволяет одному интерфейсу управлять разными типами объектов.
for account in [Account(), SavingsAccount()]:
account.deposit(100)
print(account.get_balance())
Здесь
deposit
действует по-разному в зависимости от типа аккаунта.Это выделение ключевых характеристик объекта и исключение нерелевантных. Это помогает сосредоточиться на том, "что делает" объект, а не на том, "как он это делает".
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
Shape
является абстрактным классом, определяющим интерфейс для всех форм.ООП основано на четырех принципах: инкапсуляции (скрытие деталей реализации), наследовании (создание новых классов на основе существующих), полиморфизме (один интерфейс для разных типов объектов) и абстракции (выделение ключевых характеристик). Эти принципы помогают создавать структурированный и управляемый код.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤3👾1
Anonymous Quiz
20%
threading.Thread
68%
multiprocessing.Process
7%
asyncio.Task
5%
concurrent.futures.ThreadPoolExecutor
🤯13👍1🤔1
Итератор – это объект в Python, который предоставляет последовательный доступ к элементам коллекции или последовательности данных. Итераторы используются для обхода элементов в структурах данных, таких как списки, кортежи, строки, словари и многие другие.
Возвращает сам итератор. Этот метод позволяет итератору начать итерацию заново, если это необходимо.
Возвращает следующий элемент в последовательности данных. Если достигнут конец последовательности, метод должен возбуждать исключение
StopIteration
.class MyIterator:
def __init__(self, max_num):
self.max_num = max_num
self.current_num = 1
def __iter__(self):
return self
def __next__(self):
if self.current_num <= self.max_num:
result = self.current_num
self.current_num += 1
return result
else:
raise StopIteration
# Использование итератора
iterator = MyIterator(5)
for num in iterator:
print(num)
В этом примере
MyIterator
является пользовательским итератором, который генерирует числа от 1 до заданного максимального числа. При достижении максимального числа итерация завершается с возбуждением исключения StopIteration
.Итераторы могут быть использованы в циклах
for
, для обхода данных в последовательности, или в любой другой ситуации, когда требуется последовательный доступ к элементам коллекции без необходимости хранения всей последовательности в памяти.Итераторы также играют важную роль в контексте генераторов. Генераторы - это специальный тип итераторов, создаваемых с использованием функций с ключевым словом
yield
. Генераторы позволяют генерировать значения на лету, вместо того чтобы хранить их в памяти целиком, что может быть полезно для обработки больших объемов данных или бесконечных последовательностей.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
Anonymous Quiz
33%
threading.active_count()
6%
threading.enumerate()
35%
threading.count()
26%
threading.get_threads()
💊13
Полиморфизм - это принцип ООП, согласно которому можно использовать один и тот же интерфейс для различных базовых форм данных или типов. Слово "полиморфизм" происходит от греческих слов "поли" (много) и "морфе" (форма). Этот принцип позволяет объектам использовать методы производного класса, даже если они изначально определены в базовом классе.
class Bird:
def intro(self):
print("В мире много разных птиц.")
def flight(self):
print("Большинство птиц умеют летать, но некоторые не умеют.")
class Sparrow(Bird):
def flight(self):
print("Воробьи могут летать.")
class Ostrich(Bird):
def flight(self):
print("Страусы не умеют летать.")
В этом примере у нас есть базовый класс
Bird
и два его подкласса Sparrow
и Ostrich
. Каждый подкласс переопределяет метод flight
. Здесь полиморфизм проявляется в том, что метод flight
, определенный в базовом классе, используется подклассами, но каждый подкласс дает свою реализацию этому методу.Полиморфизм важен, потому что он позволяет писать более гибкий и масштабируемый код. Благодаря ему можно создавать функции, которые могут работать с любыми классами, наследующими от базового класса, что упрощает расширение и модификацию программы.
Полиморфизм - это когда один и тот же метод можно использовать для разных объектов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤4🔥1
Anonymous Quiz
16%
threading
59%
asyncio
11%
multiprocessing
15%
concurrent.futures
❤2👍1
Словарь — это коллекция элементов, которая хранит данные в парах ключ-значение. Ключ в словаре может быть любым неизменяемым типом данных: числами, строками, кортежами. Главное требование к ключу — он должен быть уникальным в рамках одного словаря и хешируемым.
Хешируемость означает, что объект должен иметь хеш-значение, которое не изменяется на протяжении всего времени существования объекта. Это необходимо для того, чтобы Python мог быстро находить значение по ключу. Если бы ключи были изменяемыми, их хеш-значения могли бы измениться, и это привело бы к тому, что значение по ключу стало бы невозможно найти.
my_dict = {"name": "Alice", "age": 25}
my_dict = {1: "one", 2: "two"}
my_dict = {(1, 2): "point", (3, 4): "another point"}
Изменяемые типы данных, такие как списки или другие словари, не могут быть ключами, потому что они не хешируемы.
Ключи в словаре Python — это неизменяемые и хешируемые объекты, такие как строки, числа или кортежи. Это обеспечивает эффективный доступ и хранение данных. В качестве ключей используются данные, которые легко идентифицировать и которые не изменяются во время работы программы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Anonymous Quiz
80%
Класс может переопределять методы родительского класса
6%
Наследование в Python не поддерживает множественное наследование
8%
Классы в Python не могут наследовать встроенные типы данных
7%
Класс может наследовать только один другой класс
💊10🤔3👍2❤1
Объектно-ориентированное программирование (ООП) — это парадигма программирования, основанная на концепции "объектов", которые могут содержать данные в виде полей (атрибуты или свойства) и код в виде процедур (методы).
ООП используется для структурирования программы таким образом, чтобы свойства и поведения были собраны в отдельные объекты. Например, в программе для управления животными в зоопарке каждое животное может быть объектом с атрибутами, такими как имя, возраст и вид, а также методами, такими как кормление или игра. Это делает программу легко понимаемой, расширяемой и поддерживаемой.
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
return "Звуки, которые издает животное"
class Dog(Animal): # Наследование класса Animal
def speak(self): # Переопределение метода speak
return "Гав"
# Создание объекта класса Dog
my_dog = Dog("Бобик", 5)
print(my_dog.speak()) # Вывод: Гав
В этом примере
Animal
является базовым классом с методом speak
, а Dog
— производным классом, который наследует свойства Animal
и переопределяет метод speak
. Это демонстрирует наследование и полиморфизм.ООП — это метод организации программы с помощью объектов, которые объединяют данные и методы работы с этими данными. Это делает программы более понятными, удобными для разработки и поддержки. Основные принципы ООП включают инкапсуляцию, наследование, полиморфизм и абстракцию.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥3
Anonymous Quiz
20%
thread.sleep()
29%
thread.join()
16%
thread.hold()
35%
thread.wait()
Лямбда-функции — это небольшие анонимные функции, состоящие из одного выражения, результат которого является значением функции. Они определяются с помощью ключевого слова
lambda
, за которым следуют аргументы функции, двоеточие и выражение, значение которого функция должна вернуть.Лямбда-функции часто используются в тех случаях, когда необходима простая функция для кратковременного использования, и нет смысла определять полноценную функцию с помощью
def
. Это может быть полезно для сортировки или фильтрации данных, а также в качестве аргумента для функций высшего порядка, таких как map()
, filter()
и reduce()
.# Определение лямбда-функции для вычисления квадрата числа
square = lambda x: x * x
# Использование лямбда-функции
print(square(5)) # Выведет 25
# Лямбда-функция в качестве аргумента функции map()
numbers = [1, 2, 3, 4]
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers) # Выведет [1, 4, 9, 16]
# Лямбда-функция для фильтрации списка
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Выведет [2, 4]
Лямбда-функции удобны для создания небольших функций на лету, без необходимости явно определять функцию с использованием
def
. Однако стоит отметить, что использование лямбда-функций может сделать код менее читаемым, если выражение становится сложным. По этой причине рекомендуется использовать лямбда-функции для простых операций и переходить к обычному определению функций с def
для более сложной логики.лямбда-функции — это компактный способ создания анонимных функций для выполнения простых выражений. Они особенно полезны для использования в качестве аргументов для функций, работающих с коллекциями данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21
Anonymous Quiz
62%
queue.Queue.put()
12%
set.add()
14%
dict.update()
11%
list.append()
👍2❤1
MRO (Method Resolution Order) — это порядок, в котором Python ищет методы и атрибуты класса при их вызове. Этот порядок особенно важен в контексте множественного наследования, когда класс наследует поведение и атрибуты от нескольких родительских классов, и нужно четко определить, откуда именно брать эти атрибуты и методы в случае их совпадения.
MRO помогает избежать проблемы алмаза (diamond problem), которая возникает, когда два родительских класса наследуют от одного и того же базового класса, а затем эти классы сливаются в один дочерний класс. Без четко определенного MRO Python не смог бы автоматически решить, в каком порядке следует искать методы и атрибуты среди родительских классов.
Python использует алгоритм C3 Linearization для определения MRO. Этот алгоритм гарантирует, что порядок разрешения методов учитывает следующие условия:
Можно узнать MRO любого класса, используя атрибут
__mro__
или метод mro()
у самого класса.class Base:
pass
class A(Base):
pass
class B(Base):
pass
class C(A, B):
pass
print(C.mro())
В этом примере порядок разрешения методов для класса
C
будет следующим: C, A, B,
Base, object
. Это означает, что если метод вызывается для экземпляра класса C
, интерпретатор Python будет искать его сначала в C
, затем в A
, после в B
, затем в Base
и, наконец, в встроенном объекте object
, который является базовым для всех классов.MRO определяет порядок, в котором интерпретатор будет искать методы и атрибуты при их вызове в контексте множественного наследования. Это обеспечивает предсказуемость и избегает конфликтов при наследовании от нескольких классов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤1
Anonymous Quiz
55%
Протоколы позволяют проверять соответствие объектов во время выполнения
23%
Протоколы требуют явного указания реализации методов
6%
Протоколы ограничивают наследование классов
17%
Протоколы не могут использоваться с абстрактными методами
Миксин (Mixin) – это класс, предназначенный для предоставления определённых методов для использования другими классами, без необходимости становиться родительским классом для этих классов. Главная цель миксина - реализация функциональности, которую можно легко подключить к другому классу. Миксины позволяют разработчикам использовать композицию для добавления функций в классы вместо наследования, что делает структуру кода гибче и модульнее.
Применение миксинов удобно, когда одна и та же функциональность нужна в разных классах, но эти классы не должны быть связаны отношениями наследования. Таким образом, миксины позволяют избежать дублирования кода и упростить его поддержку.
class JsonMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class PersonJson(JsonMixin, Person): # Использование миксина для добавления функциональности сериализации в JSON
pass
p = PersonJson('Иван', 25)
print(p.to_json()) # Выведет строку в формате JSON, представляющую объект PersonJson
В этом примере
JsonMixin
предоставляет метод to_json
, который может сериализовать объекты класса в JSON. Класс PersonJson
наследует этот метод благодаря множественному наследованию, где JsonMixin
используется для добавления функциональности сериализации к классу Person
, не изменяя его исходный код.Использование миксинов делает код более читаемым и легко поддерживаемым, так как оно позволяет разработчикам комбинировать и переиспользовать функциональности между различными классами без изменения их иерархии наследования.
Миксин - это способ добавления функциональности к классам через множественное наследование, без необходимости изменять их иерархию. Это позволяет сделать код более модульным и легким для поддержки.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍5