2619
🐍 Канал о программировании на языке Python. Тематические уроки и лайфхаки. 👽 Админ - @it_dashka 🔊 Купить рекламу: https://telega.in/c/byteofpython 👉 Чат: @abyteofpython 👉 Поделиться с друзьями: @byteofpython
Массивы в pattern matching.
В качестве шаблонов также могут выступать массивы. Подобным шаблоны также могут содержать либо конкретные значения, либо переменные, которые передаются элементы массивов, либо символ прочерка _, если элемент массива не важен.
В данном случае функция print_people принимает массив, который, как предполагается, состоит из трех элементов, рассмотрим их в следующей части.
🐍 Укус питона // 💬 Чат // #теория #pattern_matching #массивы
Что выведет код?
x = 0Читать полностью…
def outer():
x = 1
def inner():
nonlocal x
x += 1
return x
print("A", inner(), x)
x = 5
print("B", inner(), x)
outer()
print("G", x)
👩💻 WeakRef — как избежать утечек памяти в Python
Иногда объект больше не нужен, но на него всё ещё ссылаются другие части программы. Обычная ссылка удерживает объект в памяти, а слабая ссылка (weak reference) — нет.
Она не мешает сборщику мусора удалить объект, если больше нет сильных ссылок
import weakref
class Data:
def __init__(self, name):
self.name = name
def __del__(self):
print(f"{self.name} удалён")
obj = Data("Test")
ref = weakref.ref(obj)
print(ref()) # <__main__.Data object at ...>
del obj
print(ref()) # None — объект собран GC
📌 weakref.ref() создаёт слабую ссылку: объект может быть удалён, даже если ссылка ещё существует.Читать полностью…
👩💻 Протокол дескрипторов — скрытый механизм свойств и 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 срабатывают методы дескриптора, а не прямой доступ к атрибуту.Читать полностью…
Что выведет код?
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)
👩💻 Мемоизация — ускорение функций без переписывания логики
Мемоизация — это техника кэширования результатов функций.
Если функция вызывается с теми же аргументами, результат возвращается из памяти, а не вычисляется заново
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 заняло бы секунды, а с ним — доли миллисекунды.
👩💻 Корутины — асинхронность без потоков
Корутины в 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())
📌 Здесь оба «скачивания» выполняются параллельно, хотя используется всего один поток.Читать полностью…
Что выведет код?
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())
👩💻 Декоратор @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 выглядит как атрибут, но фактически вычисляется при обращении.Читать полностью…
❓ Зачем используется метод split() в Python и когда его применять?
Метод split() разбивает строку на части по заданному разделителю и возвращает список. Это удобно для обработки текста, логов, CSV-данных и пользовательского ввода.
✅Пример:
text = "apple,banana,orange"
fruits = text.split(",")
print(fruits)
# ➜ ['apple', 'banana', 'orange']
split() удобно использовать при парсинге строк, чтении файлов, анализе данных и обработке команд. Без аргумента метод автоматически разделяет по пробелам — это особенно полезно для очистки и разбиения текста на словаЧитать полностью…
👩💻 Генераторы — ленивые последовательности без лишней памяти
Генераторы в Python создают значения "на лету", без хранения всего списка в памяти.
Это делает их идеальными для работы с большими объёмами данных и потоками
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
gen = fibonacci()
for _ in range(5):
print(next(gen))
# 0 1 1 2 3
📌 Здесь yield превращает функцию в генератор, который "запоминает" состояние между вызовами.Читать полностью…
👩💻 Замороженные датаклассы — безопасные объекты без мутаций
В Python dataclasses можно сделать неизменяемыми с помощью параметра frozen=True.
Это превращает экземпляры в безопасные структуры данных, похожие на namedtuple, но с гибкостью классов.
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(3, 5)
# p.x = 10 # ❌ Ошибка: объект заморожен
print(p) # Point(x=3, y=5)
📌 Используй frozen dataclass, если данные должны быть константными и безопасными по дизайнуЧитать полностью…
❓ Зачем используется метод remove() в Python и когда его применять?
Метод remove() удаляет первое вхождение указанного элемента из списка. Это удобно, когда нужно убрать конкретное значение, а не по индексу.
✅Пример:
fruits = ["apple", "banana", "orange", "banana"]
fruits.remove("banana")
print(fruits)
# ➜ ['apple', 'orange', 'banana']
remove() удобно использовать при очистке данных, фильтрации списков или удалении обработанных элементов. Если элемента нет, Python вызывает ValueError, поэтому перед удалением лучше проверять наличие через inЧитать полностью…
👩💻 Декораторы с аргументами — динамическое управление поведением функции
Декораторы в Python могут принимать параметры, что делает их особенно мощными.
Это позволяет менять поведение функций в зависимости от внешних условий, не переписывая код
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet():
print("Привет!")
greet()
# Привет!
# Привет!
# Привет!
📌 Здесь repeat(3) создаёт декоратор, который повторяет выполнение функции 3 разаЧитать полностью…
👩💻 Передача изменяемых объектов в функции
В Python аргументы передаются по ссылке на объект, а не по значению.
Если функция изменяет мутабельный объект (список, словарь), изменения сохраняются снаружи
def add_item(items):
items.append("новый элемент")
data = ["a", "b"]
add_item(data)
print(data) # ['a', 'b', 'новый элемент']
📌 Функция не вернула новый список — она изменила существующий. Чтобы избежать этого, передавай копию (items[:] или items.copy()).Читать полностью…
👩💻 Динамическое создание классов — метапрограммирование в чистом виде
В Python классы — это тоже объекты, и их можно создавать "на лету" с помощью функции type(). Это открывает путь к динамическому API, автоматическим моделям и DSL.
➡️ Пример:
def make_model(name, **fields):
return type(name, (object,), fields)
User = make_model("User", name="Анна", age=25)
print(User.name) # Анна
admin = User()
admin.role = "admin"
print(admin.role) # admin
📌 Здесь type() создаёт новый класс User прямо во время исполнения.Читать полностью…
👩💻 Контракты через аннотации — не просто подсказки типов
Аннотации типов (type hints) — это не только помощь IDE.
С их помощью можно внедрять контроль логики исполнения — проверять типы, значения и инварианты прямо во время работы программы.
➡️ Пример:
from typing import get_type_hints
def enforce_types(func):
hints = get_type_hints(func)
def wrapper(*args, **kwargs):
for name, arg in zip(hints, args):
if not isinstance(arg, hints[name]):
raise TypeError(f"{name} должен быть {hints[name].__name__}")
return func(*args, **kwargs)
return wrapper
@enforce_types
def greet(name: str, age: int):
print(f"{name}, {age}")
greet("Анна", 25) # ✅
greet("Анна", "25") # ❌ TypeError
📌 Здесь аннотации становятся частью исполняемого контракта, а не просто документацией.Читать полностью…
Что выведет код?
import itertoolsЧитать полностью…
lst = [[1, 2], [3]]
it = itertools.chain.from_iterable(lst)
print(next(it))
lst.append([4, 5])
print(list(it))
👩💻 Протокол итерации — как работает цикл 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.Читать полностью…
❓ Зачем используется метод 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() удобно использовать при очистке данных, форматировании строк, замене символов и шаблонов в текстах. Метод не изменяет исходную строку, что делает его безопасным для повторного использования данныхЧитать полностью…
Что выведет код?
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())
👩💻 Слотирование классов — экономия памяти и ускорение 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%) и ускоряет доступ к атрибутам.Читать полностью…
👩💻 Метаклассы — классы для создания классов
Метаклассы в 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.Читать полностью…
Что выведет код?
from contextlib import ExitStack, contextmanagerЧитать полностью…
@contextmanager
def cm(name):
print("e"+name)
try:
yield name
finally:
print("x"+name)
with ExitStack() as st:
a = st.enter_context(cm("A"))
b = st.enter_context(cm("B"))
print("body", a, b)
👩💻 Контекстные менеджеры — управление ресурсами без утечек
Контекстные менеджеры позволяют автоматически управлять ресурсами — открытыми файлами, соединениями, блокировками.
Они гарантируют освобождение ресурсов даже при ошибках
class Managed:
def __enter__(self):
print("Ресурс открыт")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Ресурс закрыт")
with Managed():
print("Работаем с ресурсом")
# Ресурс открыт
# Работаем с ресурсом
# Ресурс закрыт
📌 Метод __enter__ выполняется при входе в блок, __exit__ — при выходе, даже если возникло исключение.Читать полностью…
👩💻 Дескрипторы в Python — сердце свойств и ORM
Дескрипторы — это объекты, которые управляют доступом к атрибутам других классов через методы __get__, __set__ и __delete__.
Они лежат в основе property, @staticmethod, @classmethod и ORM вроде Django.
class Celsius:
def __get__(self, instance, owner):
return instance._temp
def __set__(self, instance, value):
if value < -273.15:
raise ValueError("Температура ниже абсолютного нуля!")
instance._temp = value
class Temperature:
temp = Celsius()
t = Temperature()
t.temp = 25
print(t.temp) # 25
📌 Дескрипторы — это низкоуровневая магия, на которой построен весь механизм Python-свойств.Читать полностью…
👩💻 Что такое свойство line-height в CSS и зачем оно нужно?
Свойство line-height управляет расстоянием между строками текста.
Это влияет не только на читаемость, но и на вертикальный ритм всего интерфейса
<p class="text">
Это пример текста с увеличенным межстрочным интервалом.
</p>
<style>
.text {
font-size: 16px;
line-height: 1.8;
}
</style>
📌 В этом примере строки располагаются свободнее, благодаря line-height: 1.8Читать полностью…
👩💻 Замыкания в Python — функции с памятью
Замыкание (closure) — это функция, которая «запоминает» значения переменных из области видимости, где она была создана, даже если эта область уже недоступна.
Это мощный инструмент для инкапсуляции состояния без классов
def counter(start=0):
count = start
def increment():
nonlocal count
count += 1
return count
return increment
click = counter(10)
print(click()) # 11
print(click()) # 12
📌 Функция increment хранит доступ к переменной count, даже после выхода из counterЧитать полностью…
👩💻 Замыкания в Python — функция внутри функции
Замыкание (closure) — это функция, которая "запоминает" значения из внешней области видимости, даже если эта область уже недоступна.
Это один из способов создавать функции с состоянием, не используя классы
def counter():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
c = counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3
📌 inner() помнит переменную count между вызовами, потому что она «замкнута» из внешней функцииЧитать полностью…
👩💻 Как Python хранит функции: всё — объекты
В Python функции — это не особый синтаксис, а объекты первого класса.
Их можно присваивать переменным, передавать в другие функции и возвращать как значения
def greet(name):
return f"Привет, {name}!"
say_hello = greet # присвоили функцию переменной
print(say_hello("Анна")) # Привет, Анна!
def run(func, arg):
print(func(arg))
run(greet, "Борис") # можно передавать функцию как аргумент
📌 Понимание, что функции — такие же объекты, как строки или списки,Читать полностью…
открывает путь к лямбдам, декораторам и функциональному стилю в Python