🐍 Укус питона 🐍
2.46K subscribers
1.07K photos
26 videos
285 links
🐍 Канал о программировании на языке Python. Тематические уроки и лайфхаки.

👽 Админ - @it_dashka
🔊 Купить рекламу: https://telega.in/c/byteofpython

👉 Чат: @abyteofpython
👉 Поделиться с друзьями: @byteofpython
Download Telegram
👩‍💻 Декоратор @property — чистый интерфейс без скобок

@property позволяет превратить методы класса в атрибуты, сохранив при этом логику вычислений или валидации.

Это делает интерфейс класса чистым и безопасным, без лишних вызовов и скобок.


➡️ Пример:

class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

@property
def area(self):
return self.width * self.height

r = Rectangle(5, 10)
print(r.area) # 50, а не r.area()


📌
Здесь area выглядит как атрибут, но фактически вычисляется при обращении.
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 Метаклассы — классы для создания классов

Метаклассы в Python определяют, как создаются и ведут себя классы.

Они дают контроль над структурой, проверкой и автоматизацией при объявлении новых классов


➡️ Пример:

class Validator(type):
def __new__(cls, name, bases, attrs):
if "validate" not in attrs:
raise TypeError("Класс должен содержать метод validate()")
return super().__new__(cls, name, bases, attrs)


class User(metaclass=Validator):
def validate(self):
return True


# class BrokenUser(metaclass=Validator): # Ошибка — нет метода validate()


📌 Здесь Validator проверяет, что каждый класс обязан иметь метод validate.
Please open Telegram to view this post
VIEW IN TELEGRAM
Что выведет код?

def f():
xs = []
for x in range(3):
xs.append(lambda: x)
ys = [(lambda: y) for y in range(3)]
return [fn() for fn in xs], [fn() for fn in ys], x

print(f())
👩‍💻 Слотирование классов — экономия памяти и ускорение Python-объектов

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

С помощью __slots__ можно задать фиксированный набор атрибутов — без словаря


➡️ Пример:

class User:
__slots__ = ("name", "age")
def __init__(self, name, age):
self.name = name
self.age = age

u = User("Анна", 25)
u.city = "Москва" # AttributeError


📌 __slots__ экономит память (до 30–40%) и ускоряет доступ к атрибутам.
Please open Telegram to view this post
VIEW IN TELEGRAM
👩‍💻 Корутины — асинхронность без потоков

Корутины в 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() в Python и когда его применять?

Метод 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() заменяет все вхождения слова "Python" на "Coding"

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)
👩‍💻 Протокол итерации — как работает цикл for под капотом

В 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
👩‍💻 Протокол дескрипторов — скрытый механизм свойств и ORM

В 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
Что выведет код?

import itertools

lst = [[1, 2], [3]]
it = itertools.chain.from_iterable(lst)
print(next(it))
lst.append([4, 5])
print(list(it))