Корутины в Python — это функции, которые приостанавливают выполнение с помощью await, освобождая поток для других задач.
Это ядро asyncio, позволяющее писать конкурентный код без блокировок
import asyncio
async def download(name, delay):
print(f"Начинаю {name}")
await asyncio.sleep(delay)
print(f"{name} готов")
async def main():
await asyncio.gather(
download("Файл 1", 2),
download("Файл 2", 1)
)
asyncio.run(main())
📌 Здесь оба «скачивания» выполняются параллельно, хотя используется всего один поток.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Что выведет код?
  import asyncio
async def worker():
await asyncio.sleep(0.05)
return "ok"
async def main():
t = asyncio.create_task(worker())
try:
await asyncio.wait_for(asyncio.shield(t), timeout=0.01)
except asyncio.TimeoutError:
print("timeout")
print(t.cancelled(), t.done())
print(await t)
asyncio.run(main())
Мемоизация — это техника кэширования результатов функций.
Если функция вызывается с теми же аргументами, результат возвращается из памяти, а не вычисляется заново
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print(fib(35)) # быстро!
📌 Здесь @lru_cache запоминает все вызовы fib().
Без него вычисление числа Фибоначчи 35 заняло бы секунды, а с ним — доли миллисекунды.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Метод
replace() возвращает новую строку, в которой все вхождения указанной подстроки заменены на другую. Это удобный способ быстро изменить текст без сложных регулярных выражений.text = "Python is hard, but Python is fun!"
new_text = text.replace("Python", "Coding")
print(new_text)
# ➜ Coding is hard, but Coding is fun!
replace() удобно использовать при очистке данных, форматировании строк, замене символов и шаблонов в текстах. Метод не изменяет исходную строку, что делает его безопасным для повторного использования данных
Please open Telegram to view this post
    VIEW IN TELEGRAM
  Что выведет код?
  class A:
def __eq__(self, o): return isinstance(o, A)
class B:
def __eq__(self, o): return isinstance(o, B)
__hash__ = object.__hash__
s = set()
try:
s.add(A())
except TypeError:
print("A")
b = B()
s.add(b)
print("B", b in s)
В Python любой объект можно сделать итерируемым, если он реализует протокол итерации — методы
__iter__() и __next__().Это основа работы for, генераторов, списковых включений и даже файлов
class Counter:
def __init__(self, limit):
self.limit = limit
self.value = 0
def __iter__(self):
return self
def __next__(self):
if self.value < self.limit:
self.value += 1
return self.value
raise StopIteration
for i in Counter(3):
print(i)
# 1 2 3
📌 Цикл for просто вызывает next() до тех пор, пока не появится StopIteration.
Please open Telegram to view this post
    VIEW IN TELEGRAM
  В Python за
@property, staticmethod, classmethod и даже ORM-поля стоит единый механизм — дескрипторы.Это объекты, которые управляют доступом к атрибутам через методы __get__, __set__, __delete__
class LoggedAttribute:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
value = instance.__dict__.get(self.name)
print(f"Получено {self.name} = {value}")
return value
def __set__(self, instance, value):
print(f"Изменено {self.name} = {value}")
instance.__dict__[self.name] = value
class User:
age = LoggedAttribute("age")
u = User()
u.age = 30
print(u.age)
📌 При обращении к u.age срабатывают методы дескриптора, а не прямой доступ к атрибуту.
Please open Telegram to view this post
    VIEW IN TELEGRAM