Python для пацанов.
134 subscribers
2 photos
9 links
"Серьезный" разбор языка программирования Пайтон для серьезных пацанов.
Download Telegram
#ПервыйКодНаРайоне
О, братишка, сейчас поговорим про reduce. Эта функция в Питоне - как крутой барыга на рынке, который умеет из кучи мелочи делать одну большую котлету. Собирает всё в кучу и выдает тебе финальный результат. Чтобы пользоваться reduce, надо подключить его откуда? Правильно, из модуля functools.

Что такое reduce?

Функция reduce принимает два аргумента: функцию и последовательность. Функция должна быть такой, что принимает два аргумента, а reduce применяет её ко всем элементам списка, шаг за шагом, сокращая список до одного единственного значения. Это как если бы ты складывал деньги в копилку: кидаешь одну монету, потом другую, и так, пока не сложишь всё.

Примеры использования reduce

Пример №1: Суммирование списка чисел

Допустим, у тебя есть список бабок, которые ты должен взять с братвы, и ты хочешь узнать, сколько всего бабок тебе обещали.

from functools import reduce

# Список бабок
babki = [100, 200, 300, 400]

# Функция для суммирования
def summa(x, y):
return x + y

# Используем reduce для суммирования
total_babki = reduce(summa, babki)
print(total_babki) # Выведет 1000


Пример №2: Нахождение максимального числа в списке

Если тебе нужно выбрать самого богатого братана из списка долгов, то reduce поможет и с этим.

# Список долгов братвы
dolgi = [100, 200, 500, 300]

# Функция для нахождения максимума
def max_dolg(x, y):
return x if x > y else y

# Используем reduce для нахождения максимального долга
max_dolg = reduce(max_dolg, dolgi)
print(max_dolg) # Выведет 500


Пример №3: Умножение всех чисел в списке

Ты хочешь узнать, во сколько раз увеличится твой капитал, если каждый день умножать его на какой-то коэффициент.

# Коэффициенты роста капитала за 4 дня
coefficients = [1.1, 1.2, 1.3, 1.4]

# Функция для умножения
def umnozhit(x, y):
return x * y

# Используем reduce для расчета итогового увеличения
total_growth = reduce(umnozhit, coefficients)
print(f"Капитал увеличится в {total_growth:.2f} раз") # Форматируем вывод, чтобы было красиво


Вот так, бро, reduce работает как зверь, когда дело доходит до объединения всего в одно целое. На улицах это как собрать всю братву для большой тусы: по одному они мало что могут, а вместе - сила.

#ПервыйКодНаРайоне
👍3💩1
#Асинхронность на питоне — это как когда у тебя много дел, и ты хочешь все успеть, но времени в обрез. Представь, ты на районе, и у тебя куча дел: надо закинуть вещи в стиралку, сварить макароны и ответить корешу в телеге. В идеале ты бы хотел делать это всё одновременно, чтобы не тратить время зря.

Так вот, в программировании тоже самое. У тебя есть задачи, которые могут долго выполняться, например, запрос на сервер или чтение файла. Если выполнять их последовательно, ты будешь сидеть и ждать каждую задачу, как будто в очереди за шаурмой.

Асинхронность позволяет запускать задачи параллельно, как будто у тебя несколько рук. В Python это делается с помощью ключевых слов async и await.

Вот как это выглядит на коде:

import asyncio

async def стиралка():
print("Закинул вещи в стиралку...")
await asyncio.sleep(5) # стиралка работает
print("Вещи постираны!")

async def макароны():
print("Поставил воду на макароны...")
await asyncio.sleep(3) # вода закипает
print("Макароны сварены!")

async def отвечаю_корешу():
print("Ответил корешу в телеге...")
await asyncio.sleep(1) # печатаешь сообщение
print("Сообщение отправлено!")

async def главный_план():
await asyncio.gather(стиралка(), макароны(), отвечаю_корешу())

# Запуск программы
asyncio.run(главный_план())


Что происходит в этом коде:

1. Ты запускаешь все три задачи параллельно с asyncio.gather().
2. Пока стиралка работает, ты можешь заняться макаронами.
3. И пока вода закипает, ты можешь ответить корешу.

Вместо того чтобы ждать, пока каждая задача выполнится, ты используешь своё время эффективно, как настоящий мастер тайм-менеджмента на районе. Асинхронность в Python — это как будто у тебя суперспособности делать всё и сразу, не тратя время на ожидание.
👏4💩1
Братва, давайте обсудим, когда нужно профилировать работу кода и какие инструменты у нас для этого есть. Это как проверка твоей тачки на сервисе: ты хочешь знать, где у тебя пробелы, что можно улучшить и где ускориться, чтобы гонять еще быстрее.

Когда нужно профилировать код?

Профилирование нужно, когда:

1. Код работает медленно: Если твой код выполняется дольше, чем ты ожидал, профилирование поможет найти узкие места.
2. Большое потребление ресурсов: Если программа жрет слишком много памяти или процессорного времени.
3. Неоптимальные алгоритмы: Когда тебе кажется, что можно оптимизировать алгоритмы, но не знаешь, где именно.
4. Проверка производительности: После внесения изменений или рефакторинга нужно убедиться, что все стало работать не хуже, а лучше.

Инструменты для профилирования

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

1. cProfile

cProfile — это встроенный в Питон модуль для профилирования. Он покажет тебе, сколько времени занимает каждая функция.

Пример использования cProfile

import cProfile

def main():
# Твой код здесь
total = 0
for i in range(1000000):
total += i
print(total)

cProfile.run('main()')


Этот код покажет тебе подробный отчет о времени выполнения каждой части твоего кода.

2. timeit

timeit — это модуль для измерения времени выполнения небольших участков кода. Он полезен, когда тебе нужно проверить, какой из двух фрагментов кода работает быстрее.

Пример использования timeit

import timeit

# Первый вариант кода
setup_code = "from math import sqrt"
test_code_1 = """
def compute():
result = []
for i in range(100):
result.append(sqrt(i))
return result
"""
# Второй вариант кода
test_code_2 = """
def compute():
return [sqrt(i) for i in range(100)]
"""

time_1 = timeit.timeit(setup=setup_code, stmt=test_code_1, number=10000)
time_2 = timeit.timeit(setup=setup_code, stmt=test_code_2, number=10000)

print(f"Время первого варианта: {time_1}")
print(f"Время второго варианта: {time_2}")


Этот код покажет тебе, какой вариант выполняется быстрее.

3. memory_profiler

memory_profiler — это инструмент для отслеживания использования памяти твоим кодом. Он поможет найти места, где память тратится впустую.

Пример использования memory_profiler

from memory_profiler import profile

@profile
def main():
a = [i for i in range(100000)]
b = [x * 2 for x in a]
del a
return b

if __name__ == '__main__':
main()


Запусти этот код и увидишь, как используется память в каждом участке функции.

Профилирование — это как техосмотр твоей тачки. Ты хочешь знать, где у тебя слабые места, и что можно подтянуть, чтобы все работало как часы. Используй cProfile для общего профилирования, timeit для проверки времени выполнения небольших фрагментов кода и memory_profiler для отслеживания потребления памяти. Так ты всегда будешь на коне и твой код будет летать как ракета!
👍4💩1
Окей, братва, сейчас я вам расскажу про модули в Питоне и как использовать файл __init__.py с фишками. Это как уметь управлять своим районом: знать, где кто живет, как всех организовать и сделать так, чтобы всё работало четко и гладко.

Что такое модуль?

Модуль в Питоне — это просто файл с кодом, который ты можешь импортировать и использовать в других частях своей программы. Например, у тебя есть файл math_functions.py, где ты хранишь все свои математические функции. Этот файл и есть модуль.

# math_functions.py

def add(x, y):
return x + y

def subtract(x, y):
return x - y


Что такое пакет?

Пакет — это как набор модулей, собранных в одну папку. Пакет позволяет структурировать код, делая его организованным и удобным для навигации. Чтобы Питон понял, что папка является пакетом, в ней должен быть файл __init__.py.

Создание пакета

Допустим, у тебя есть проект с такой структурой:

my_project/
math_functions.py
string_functions.py


Ты можешь организовать их в пакет:

my_project/
my_package/
__init__.py
math_functions.py
string_functions.py


Что такое `__init__.py`?

__init__.py — это специальный файл, который позволяет Питону понимать, что эта папка является пакетом. Он может быть пустым, но обычно в нем можно описать код, который должен выполняться при импорте пакета.

Пример использования `__init__.py`

Давайте сделаем так, чтобы наш пакет my_package автоматически импортировал все функции из своих модулей. Вот как может выглядеть __init__.py:

# my_project/my_package/__init__.py

from .math_functions import add, subtract
from .string_functions import uppercase, lowercase


Теперь ты можешь импортировать функции прямо из пакета:

# main.py

from my_package import add, uppercase

print(add(2, 3)) # Выведет 5
print(uppercase('hello')) # Выведет HELLO


Фишки с `__init__.py`

1. Удобный импорт


Ты можешь упростить импорт, собирая все нужные функции и классы в __init__.py, чтобы не писать длинные пути при импорте.

# my_project/my_package/__init__.py

from .math_functions import add, subtract
from .string_functions import uppercase, lowercase

__all__ = ['add', 'subtract', 'uppercase', 'lowercase']


Теперь импорт будет выглядеть еще проще:

from my_package import *

2. Инициализация пакета

Ты можешь выполнять код при загрузке пакета, например, устанавливать конфигурации или проверять зависимости.

# my_project/my_package/__init__.py

print("Загружается пакет my_package")

# Инициализация настроек
config = {
'setting_1': True,
'setting_2': 'default_value'
}


3. Подпакеты и вложенные пакеты

Если у тебя сложная структура проекта, ты можешь иметь вложенные пакеты:

my_project/
my_package/
__init__.py
math_functions.py
string_functions.py
sub_package/
__init__.py
helper_functions.py


В __init__.py пакета sub_package можно описывать импорт функций из вложенного пакета:

# my_project/my_package/sub_package/__init__.py

from .helper_functions import helper_function

4. Динамическая загрузка модулей

Ты можешь динамически загружать модули в зависимости от условий:

# my_project/my_package/__init__.py

import os

if os.getenv('USE_ADVANCED_FUNCTIONS') == '1':
from .advanced_math_functions import advanced_add
else:
from .basic_math_functions import basic_add as add


Заключение

Пакеты и модули помогают тебе держать код в порядке, как на районе. Файл __init__.py делает пакет мощным инструментом, позволяя управлять импортом, инициализацией и организацией кода. Используй эти фишки, чтобы твой проект был четким и организованным, как элитный район.
👍8🥰1💩1
Йо, пацаны, сегодня про важное! 😎🐍

Знаете, что такое GIL? Это такой "Главный Интерпретаторский Замок", который держит ваш Питон в узде, пока он шпарит код в одном потоке. Но вот что интересно — в новом Питоне 3.13 чуваки из Python решили, что можно и без этого замка жить. Казалось бы, свобода для всех потоков, но тут есть засада!

🔥 Если ты компилишь Python без GIL и запускаешь один поток — привет, тормоза! Почему? Ну, потому что система теперь тратит время на то, чтобы сделать всё безопасным для многопоточности. В итоге твой код тормозит примерно на 40% сильнее, чем в обычной версии с GIL! Да, это как если бы ты снял шлем на гонках и надеялся, что ветер сам разрулит — но нет, тормоза будут!

💡 Когда это важно? Если у тебя обычный код, который не гоняет сотни потоков, то без GIL ты тупо теряешь скорость, как будто тачку на ручник поставил. Free-threaded Питон — штука крутая для тех, кто шарит в многопоточности, но если у тебя один поток, держись подальше, пока не прикрутят норм оптимизации.

🥶 Но есть надежда! Говорят, что в Python 3.14 сделают так, что без GIL код будет тормозить всего на 10%, а это уже не так обидно. Но это потом, а пока — не гоняй, где не надо!

Вывод для пацанов: если твой код одинокий волк (однопоточный), то GIL тебе друг. А если ты хочешь жить на грани и жмешь на газ в многопоточке — пробуй без GIL, но будь готов к тормозам в версии 3.13. 🚗💨

Понравилось? Лайк и подписка, вы ж знаете, куда нажать! 💪
3👍2🔥21💩1
🔥 Продолжаем базарить про Python 3.13! 🔥

В прошлом посте мы уже говорили про те самые 40% потери производительности в однопоточных программах без GIL. Но не всё так плохо, пацаны. Давайте разберём, что ещё нас ждёт в Python 3.13, и как это вообще использовать.

Дата релиза и что это значит для тебя 📅

Python 3.13 выходит уже 7 октября 2024 года! Это значит, что скоро можно будет официально юзать версии без GIL. Это не просто мелкая обнова, это настоящая революция для тех, кто хочет выжимать из многопоточности максимум. Твой код будет реально параллельно работать на всех ядрах процессора, как настоящий чемпион.

Как запустить Free-threading? 🛠

1. Windows и macOS: качай обнову с официального сайта и просто выбирай установку без GIL.
2. Линукс или самосборщики: компилируешь с флагом --disable-gil, и готово!

Как чекнуть, отключён ли GIL? 🔍

Чтобы убедиться, что ты реально отключил GIL, запускай:

python -VV


Если увидишь надпись "experimental free-threading build", значит, ты сделал всё по красоте.

Можно ещё проверить в рантайме через функцию

sys._is_gil_enabled()



Что по безопасности в многопоточке? ⚠️

Когда работаешь без GIL, стоит быть осторожным:

- Итераторы: не дели один и тот же итератор на все потоки — это может привести к проблемам.
- Frame объекты: не трогай их в других потоках, это может крашнуть программу.


Иммортализация объектов — это чё? 🛡

Теперь некоторые объекты в free-threading режиме становятся бессмертными. Это значит, что они больше не будут удаляться из памяти. Это касается функций, модулей, методов и строк. Учти, если таких объектов будет много, твоя оперативка быстро забьётся. Иными словами - утечка памяти. Но в 3.14 это тоже обещали забороть.

Что по C-расширениям? 🔧

Если твои проекты зависят от C-расширений, знай, что не все из них поддерживают работу без GIL. Если вдруг что, GIL включится автоматически, и ты увидишь предупреждение.
Это касается например таких важных либ, как lxml, на базе которой например сделаны самые быстрые части BeautifulSoup и много чего еще.
Потому твой какой нибудь парсер скорее всего нормально в free-trading 3.13 не заработает, братан.
Но со временем чуваки доработают и этот момент, причем есть шанс что в промежуточных версиях до 3.14 (ноэтонеточно)

Итог: как выжать максимум из Python 3.13? 💪

1. Готовься к многопоточности: вырубай GIL, если твой проект реально нуждается в многопоточности, и кайфуй от полной загрузки всех ядер процессора.
2. Однопоточный код? Подожди 3.14: если твой проект однопоточный, лучше дождись версии Python 3.14, где ребята обещают снизить потери производительности до 10%.
3. Иммортализация объектов: если у тебя много модулей и строк — будь готов к увеличению потребления памяти.

Python 3.13 уже 7 октября 2024! Но использовать его нужно если ты чётко осознаешь последствия!
👍3🔥3💩1💯1
"Братишки, вот как `builtins` решает ваши проблемы с `input()`"

Чё, пацаны, когда юзаешь питончик, всё круто, пока не надо бахнуть input(). И тут твой скрипт тормозит на месте и ждёт, пока ты что-то влупишь с клавы, да? Не порядок. Но тут я покажу, как сделать, чтобы input() играл по твоим правилам и вообще не парил мозг. Всё это на базе builtins — самого матерого пацана в питонячей тусовке.

Кто такой builtins?

builtins — это как главный босс в Python. Он отвечает за всю стандартную движуху, типа print(), len(), input() и т.д. Его всегда можно вызвать по фасту, даже если ты не подключал его напрямую. Но вот фишка — ты можешь подкрутить его и заставить выполнять твои команды.

Короче, как мы будем хакать input()?

Чё мы сделаем: бахнем декоратор и вставим туда замутку с подменой input(). Смотри:

1. Декорим твою функцию так, чтобы вместо обычного input() скрипт сам подставлял то, что тебе надо.
2. Это всё будет кататься через глобальный объект __builtins__, где input() живёт по дефолту.
3. Мы временно заменим его своим и обратно всё откатим после, чтобы никто и не догадался, что мы мутим.

Пример кода

def auto_input(mock_values):
def decorator(func):
def wrapper(*args, **kwargs):
# Сохраняем реальный `input`
original_input = __builtins__.input
# Врубаем наши данные вместо реального инпута
values = iter(mock_values)
__builtins__.input = lambda _: next(values)
# Вызов твоей функции
result = func(*args, **kwargs)
# Возвращаем всё как было
__builtins__.input = original_input
return result
return wrapper
return decorator


Как это юзать?

Теперь ты можешь кидать это куда угодно. Надо автоматом влепить значения в input() — не вопрос:

@auto_input(["значение1", "значение2"])
def my_function():
first = input("Введите первое значение: ")
second = input("Введите второе значение: ")
print(f"Введено: {first}, {second}")

my_function()


Чё будет:
Скрипт больше не будет сидеть в ожидании, когда ты там что-то вкатишь. Он сам себе всё подставит, как ты задал в декораторе. Нормально, да?

Зачем это нужно?

Ну, представь ты тестируешь функции или автоматизируешь штуки, где на каждое input() забивать свои данные вручную — это как бежать марафон на руках. С этой темой ты упростишь себе жизнь и ускоришь тесты. На продакшн не советую так делать, но для теста или всяких хитрых махинаций — это огонь.

Важный момент

После того как поработали с подменой, мы всегда возвращаем старый добрый input(), иначе можно устроить хаос, и другие функции начнут путаться, как оно вообще работает.

Резюмирую:

builtins — это тот парень, которого ты можешь взломать и заставить делать работу по твоему. Главное — делать это по уму, чтобы никто не палил тему. Подменяй input(), рули своим кодом и не давай ему тебя держать в заложниках!

Так что, пацаны, юзайте правильно — и будет вам Python с кайфом.

#декоратор #хак
😎6👍3😁2💩2🤮1
👋 *Эй, пацаны и девчата!* Сегодня покажу, как кодить на Python так, чтобы выглядело "чётко" и стильно, как белые кроссы. Берём фишки, чтобы ваш код был не просто норм, а 🔝!

1. Списочные включения 🔥

Не канает:
squares = []
for x in range(10):
squares.append(x ** 2)


Как надо:
squares = [x ** 2 for x in range(10)]

🎤 *Коммент*: Одной строкой создаем список. Чисто — чики-брики, 👌 и сразу порядок.

2. Генераторы 🚀

Как не стоит:
large_list = [x * x for x in range(1000000)]

Как надо:
large_generator = (x * x for x in range(1000000))

🎤 *Коммент*: Вместо создания огромного списка берём генератор. Память не жрёт, 💾 особенно если данных много.

3. Распаковка кортежей 💼

Плохо:
point = (10, 20)
x = point[0]
y = point[1]

Как надо:
x, y = point

🎤 *Коммент*: Одной строкой раскидываем значения по переменным, как надо, а не как в лавке с вещами.

4. enumerate() — не парься с индексом 👀

Сложный путь:
i = 0
for item in items:
print(i, item)
i += 1

Как надо:
for i, item in enumerate(items):
print(i, item)

🎤 *Коммент*: enumerate() даёт и элемент, и индекс. Экономит строки и 🌐 понятно.

5. Менеджер контекста with 📂

Старый способ:
file = open('data.txt', 'r')
try:
data = file.read()
finally:
file.close()

Как надо:
with open('data.txt', 'r') as file:
data = file.read()

🎤 *Коммент*: with сам закроет файл, как завершил. 👋 Экономия времени.

6. Методы словаря get() и setdefault() 🔑

Долго:
if key in my_dict:
value = my_dict[key]
else:
value = default_value

Быстрее:
value = my_dict.get(key, default_value)

🎤 *Коммент*: Одной строкой получаем значение. 🤏 Легче понять и экономим символы.

7. Обмен значениями через множественное присваивание 🤝

Лишние шаги:
temp = a
a = b
b = temp

Как профи:
a, b = b, a

🎤 *Коммент*: Обмениваем значения без временных переменных, как в обменнике.

8. any() и all() — проверка сразу всех 🕵️‍♂️

Не оптимально:
def has_negative(nums):
for num in nums:
if num < 0:
return True
return False

Лучше так:
def has_negative(nums):
return any(num < 0 for num in nums)

🎤 *Коммент*: any() проверяет сразу всё. Экономия строк и 💪 эффективность.

9. f-строки 🎫

Устарело:
name = 'Alice'
age = 30
message = 'Name: %s, Age: %d' % (name, age)

Современный подход:
name = 'Alice'
age = 30
message = f'Name: {name}, Age: {age}'

🎤 *Коммент*: f-строки дают возможность вставлять значения прямо в текст. 💬 Быстрее и читаемо.

10. PEP 8 🧑‍🏫

Как не надо:
def calculateSum(a,b):
return(a+b)

Правильно:
def calculate_sum(a, b):
return a + b

🎤 *Коммент*: PEP 8 — это стиль, 👔 порядок и уважение. Если хочешь кодить как профи, придерживайся норм.

Доп. Практики 🛠

- Избегаем изменяемых объектов по умолчанию:
Потенциальная проблема:

  def append_to_list(value, my_list=[]):
my_list.append(value)
return my_list

Надёжно:

  def append_to_list(value, my_list=None):
if my_list is None:
my_list = []
my_list.append(value)
return my_list


🎤 *Коммент*: Изменяемые значения как дефолты могут привести к багам. 🛑 Лучше использовать None.

- Обработка ошибок через исключения:
Не оптимально:

  def divide(a, b):
if b == 0:
return None
else:
return a / b

Используем try-except:

  def divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Деление на ноль!")


🎤 *Коммент*: Исключения — это 👌 чистый способ ловить ошибки.


⚡️ *Вот такие дела, ребята! Применяйте эти фишки и пишите не просто рабочий код, а настоящий Python с душой!*
👍7💩32🤡2👎1
Эй, народ, послушайте сюда! Сейчас я вам расскажу про такую фишку, как memoryview, и почему без него иногда ну вообще никуда.

Что за `memoryview` и зачем он нужен?

Представьте, вы пишете какой-нибудь супербыстрый сетевой сервис или игру, где важна каждая миллисекунда. Вам нужно работать с данными напрямую, без лишних копирований и задержек. Обычные методы не катят — они медленные и жрут память как не в себя.

memoryview — это как прямой доступ к памяти. Он позволяет смотреть на данные без копирования, работать с ними быстро и эффективно. Это как если бы вы получили мастер-ключ от всех данных и могли бы делать с ними всё, что душе угодно.

Реальный пример: Быстрая обработка сетевых данных

Допустим, вы пилите свой сервер для онлайн-игры или чата. Данные летят пачками, и вам нужно их обрабатывать на лету. Если каждый раз копировать данные, ваш сервер начнёт тупить и лагать. А это никому не нужно, верно?

Вот как `memoryview` спасает ситуацию:

Вы получаете данные из сокета и создаёте memoryview. Теперь вы можете быстро парсить протоколы, читать заголовки, проверять данные — и всё это без копирования и лишней траты памяти.

import socket

# Создаём сокет и принимаем данные
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('example.com', 80))
sock.sendall(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')

data = sock.recv(4096)
mv = memoryview(data)

# Предположим, первые 4 байта — это длина следующего сообщения
msg_length = int.from_bytes(mv[:4], 'big')

# Достаём само сообщение
message = mv[4:4+msg_length]

# Обрабатываем сообщение без копирования
process_message(message)


Почему это круто?

- Скорость: Нет лишних копирований данных. Вы работаете напрямую с буфером.
- Экономия памяти: При больших объёмах данных это критично.
- Гибкость: Можно легко работать с различными протоколами и форматами данных.

Ещё один пример: Изменение частей данных в массиве

Допустим, вы работаете с изображением или звуком, и вам нужно быстро менять части данных. С memoryview это делается на раз-два.

# Имеем изменяемый массив байтов, например, изображение
buffer = bytearray(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09')

# Создаём memoryview
mv = memoryview(buffer)

# Меняем часть данных напрямую
mv[2:5] = b'\xFF\xFF\xFF'

print(buffer) # Выведет: bytearray(b'\x00\x01\xff\xff\xff\x05\x06\x07\x08\x09')


Где без `memoryview` никуда?

- Работа с бинарными протоколами: Сетевые приложения, где нужно быстро парсить и формировать пакеты данных.
- Графика и мультимедиа: Обработка изображений, видео или аудио в реальном времени.
- Интеграция с низкоуровневыми библиотеками: Когда нужно передавать данные в C-расширения или использовать буферные интерфейсы.

Например, интеграция с NumPy

Если вы работаете с массивами NumPy и хотите передать данные в библиотеку, которая использует буферный интерфейс, memoryview позволяет сделать это без копирования.

import numpy as np

# Создаём массив NumPy
arr = np.arange(10, dtype='int32')

# Создаём memoryview
mv = memoryview(arr)

# Передаём mv в функцию, ожидающую буферный интерфейс
some_function_that_uses_buffer(mv)


Заключение

memoryview — это мощный инструмент для тех, кто хочет выжать максимум из Python. Он позволяет работать с данными на низком уровне, экономить память и ускорять выполнение кода. Так что, если вы стремитесь к топовой производительности и хотите, чтобы ваш код был быстрым, как пуля, берите на вооружение memoryview и творите чудеса!
👍7🔥3💩3🫡2👎1
🔥 UV: Менеджер пакетов для Python для настоящих пацанов 🔥

Йо, братва! Если вы до сих пор юзаете старые инструменты типа pip и pipenv, пора перейти на новый движ — UV. Это не просто менеджер пакетов, а целый универальный инструмент, который всё решает: ставит зависимости, создает виртуалки, даже нужную версию Python подкачивает. Всё это на Rust, так что скорость — как ракета 🚀.

---

💥 Чё такое UV?

Представьте, что у вас один инструмент, который заменяет сразу кучу утилит:
• _pip_
• _pip-tools_
• _virtualenv_
• _pyenv_
• _pipx_
и даже Git-фишки!
С UV вам не надо мутиться с кучей команд — одна команда, и все работает, как часы ⏱️.

---

⚡️ Основные фишки UV:

- Скорость — молния ⚡️
Благодаря Rust, установка пакетов и разрешение зависимостей происходит в 10–100 раз быстрее, чем у старых добрых инструментов. Кэш включен — и скорость супер!

- Все в одном 🎯
UV ставит зависимости, создает виртуалки и даже управляет версиями Python. Забудьте про разрозненные утилиты!

- Простота использования 🤙
Команды похожи на привычные:
  uv pip install flask
uv pip compile -o requirements.txt
uv pip sync requirements.txt

Для виртуалок и Python:
  uv venv --python 3.11.9
uv python install 3.12


- Git-интеграция 🔥
Хочешь брать зависимости прямо из Git-реп? UV тащит их, кэширует и обновляет без заморочек. Если нужны самые свежие фичи, — это твой выбор!

---

🛠 Как юзать UV на практике:

*Инициализация проекта*
uv init my_project
cd my_project

Структура проекта готова, появляется pyproject.toml и .python-version. Всё по понятиям!

*Добавление зависимостей*
uv add "fastapi>=0.70"

Зависимости пишутся в конфиг, lockfile генерится — у вас всегда один и тот же билд на всех машинах.

*Создание виртуального окружения*
uv python install 3.11.9
uv venv --python 3.11.9

Нужную версию Python ставит UV и создает виртуалку без лишних заморочек.

*Запуск утилит и скриптов*
Для утилит, типа Ruff:
uvx ruff check .

А если есть скрипт с инлайн-зависимостями, добавляешь так:
uv add --script my_script.py "requests" "rich"
uv run my_script.py

Запускается скрипт в изолированном окружении — все как надо.

---

🚀 Git-движуха в UV

Слушай, UV не только пакеты ставит — он умеет тащить зависимости прямо из Git! Если тебе нужна свежая версия библиотеки из репы, указывай её, а UV все схватит, закэширует и подтянет обновления. Это реально спасает, когда работаешь с экспериментальными фичами или хочешь всегда быть на гребне волны 🌊.

---

🤘 Итог

UV — это настоящий хайп в мире Python. Он объединяет все, что нужно для быстрой и удобной разработки, и уже стал стандартом для настоящих пацанов, которые ценят свое время и не любят морочиться с настройками. Если хочешь работать быстро, четко и без лишних заморочек — переходи на UV, бро. Это будущее Python, и оно уже наступило!

Если есть вопросы или нужна помощь — пиши, всегда на связи! ✌️😎
1🔥5👍41💩1
PEP 750: t-строки в 3.14

В питон добавили еще один способ форматировать строки. Теперь – со специальным АПИ для внешних интеграций.

- PEP: https://peps.python.org/pep-0750
- Реализация: https://github.com/python/cpython/pull/132662

Основная причина: использовать f строки удобно, но нет никакого АПИ для перехвата момента "вставки" или интерполяции значений. Например, при форматировании html или sql – требуется специальным образом делать escape для значений. И раньше код вида f"<div>{template}</div>" представлял собой дыру в безопасности и потенциальное место для XSS.

string.templatelib.Template

Новый префикс t не будет создавать объект str, он будет создавать объект класса string.templatelib.Template:


>>> user = 'sobolevn'
>>> template = t"Hi, {user}"
>>> template
Template(strings=('Hi, ', ''), interpolations=(Interpolation('sobolevn', 'user', None, ''),))

>>> from string.templatelib import Template
>>> isinstance(template, Template)
True


Обратите внимание, что при создании template – у нас не произошло форматирование сразу. Мы создали объект, у которого есть свойства strings и interpolations, из которых можно собрать финальную отформатированную строку.

Давайте посмотрим на примере. Допустим, мы хотим формировать URL из наших данных:


>>> domain = 'example.com'
>>> query = 'python string formatting is too complex'
>>> template = t'https://{domain}?q={query}'


И сам код логики форматирования, где мы будем вставлять значения разным способом. Если у нас шаблон query, то мы будем использовать quote_plus для его форматирования. Остальные значения – будем вставлять как есть:


>>> from string.templatelib import Template, Interpolation
>>> from urllib.parse import quote_plus

>>> def format_url(template: Template) -> str:
... parts = []
... for part in template:
... match part:
... case str() as s: # regular string
... parts.append(s)
... case Interpolation(value, expression='query'):
... parts.append(quote_plus(value))
... case Interpolation(value):
... parts.append(value)
... return ''.join(parts)


И вот результат:


>>> format_url(template)
'https://example.com?q=python+string+formatting+is+too+complex'


Только теперь наш Template был отформатирован. Нами. Ручками.
У нас есть полный контроль за процессом форматирования. Вот в чем суть данного ПЕПа.

Фичи одной строкой

- Работает = как обычно в f строках: t'{user=}'
- Есть привычные определители формата: !r, !s, .2f, тд
- t строки можно конкатенировать: t'Hello' + t' , world!' и t'Hello, ' + 'world'
- Поддерживается режим raw строк: rt"Hi \n!"

Как устроено внутри?

Интересные места имплементации:
- Изменения лексера
- Изменения грамматики языка
- Новое CAPI _PyTemplate
- Новые классы Template и Interpolation написанные на C
- Новый байткод BUILD_INTERPOLATION и BUILD_TEMPLATE


>>> import dis
>>> user = 'sobolevn'
>>> dis.dis('t"Hi, {user}"')
0 RESUME 0

1 LOAD_CONST 2 (('Hi, ', ''))
LOAD_NAME 0 (user)
LOAD_CONST 1 ('user')
BUILD_INTERPOLATION 2
BUILD_TUPLE 1
BUILD_TEMPLATE
RETURN_VALUE


Обсуждение: как вам еще один способ форматирования строк?

| Поддержать | YouTube | GitHub | Чат |
👍71