Pythoner
7.23K subscribers
860 photos
27 videos
4 files
654 links
Полезные материалы по Python, которые будут интересны опытному и начинающему разработчику.

Сотрудничество - @flattys
Цены - @serpent_media

Канал на бирже: https://telega.in/c/pythonercode
Download Telegram
✈️Fugue — это мощный инструмент для обработки данных, который объединяет возможности Python и SQL. Она разработана для упрощения обработки данных в распределенных системах, таких как Apache Spark и Dask, и позволяет писать код, который будет работать как в локальном режиме, так и в распределенном.

➡️Основные возможеости:
💬Упрощение кода для обработки данных
💬Поддержка различных движков выполнения (Spark, Dask)
💬Поддержка SQL, что позволяет использованию знакомого синтаксиса для работы с данными

➡️Пример использования:
# Установка библиотеки
!pip install fugue

# Импорт необходимых модулей
from fugue import FugueEngine
from fugue.spark import SparkExecutionEngine

# Пример обработки данных
def process_data(df):
return df.groupby("category").agg({"value": "sum"})

# Инициализация движка
engine = SparkExecutionEngine()

# Чтение данных
data = [
{"category": "A", "value": 10},
{"category": "B", "value": 20},
{"category": "A", "value": 30},
]

# Обработка данных
result = engine.run(data, process_data)

# Вывод результата
print(result)

⬆️В этом примере мы определили функцию обработки данных, которая группирует данные по категории и суммирует значения. Далее инициализировали движок для выполнения фрейма данных и запустили обработку с использованием локальных данных, и вывели результат.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍54🔥3
➡️Монолитная архитектура

Монолитная архитектура представляет собой традиционный подход к разработке приложений, где все компоненты тесно связаны и работают как единое целое.

Преимущества:
💬Простота разработки и развертывания
💬Легкость в отладке и тестировании
💬Высокая производительность из-за отсутствия сетевых задержек между компонентами

Недостатки:
💬Сложность масштабирования отдельных компонентов
💬Затруднительное внедрение новых технологий
💬Риск "снежного кома" при росте сложности проекта

➡️Микросервисная архитектура

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

Преимущества:
💬Гибкость в выборе технологий для каждого сервиса
💬Легкость масштабирования отдельных компонентов
💬Возможность независимой разработки и развертывания сервисов

Недостатки:
💬Сложность в управлении и оркестрации множества сервисов
💬Повышенные требования к инфраструктуре
💬Потенциальные проблемы с производительностью из-за сетевых взаимодействий

🔎Что выбрать для вашего проекта?

Выбор архитектуры зависит от нескольких факторов:

➡️Выбирайте монолитную архитектуру, если:
💬У вас небольшой проект или стартап
💬Вам нужно быстро вывести продукт на рынок
💬У вас ограниченные ресурсы для разработки и поддержки

➡️Выбирайте микросервисную архитектуру, если:
💬У вас крупный проект с множеством функций
💬Вам нужна высокая масштабируемость и гибкость
💬У вас есть ресурсы для управления сложной инфраструктурой

➡️Заключение

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

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍4🔥3
✈️Библиотека functools в Python - это настоящая сокровищница для разработчиков, стремящихся оптимизировать свой код и расширить функциональные возможности языка. Хотя многие знакомы с такими популярными инструментами, как @lru_cache и partial, эта библиотека скрывает ряд менее известных, но не менее полезных функций.

➡️reduce(): мощь функционального программирования

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

Пример использования:
from functools import reduce

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # Выведет: 120


➡️singledispatch: элегантное решение для перегрузки функций

@singledispatch позволяет создавать функции, которые ведут себя по-разному в зависимости от типа переданного аргумента. Это элегантная альтернатива множественным условным операторам.
from functools import singledispatch

@singledispatch
def process(arg):
print(f"Обработка объекта: {arg}")

@process.register(int)
def _(arg):
print(f"Обработка целого числа: {arg}")

@process.register(list)
def _(arg):
print(f"Обработка списка длиной {len(arg)}")

process("строка") # Обработка объекта: строка
process(42) # Обработка целого числа: 42
process([1, 2, 3]) # Обработка списка длиной 3


➡️total_ordering: автоматическое создание методов сравнения

Декоратор @total_ordering значительно упрощает реализацию классов, поддерживающих операции упорядочивания. Достаточно определить методы eq() и один из методов сравнения (lt, le, gt или ge), а остальные будут автоматически созданы.
from functools import total_ordering

@total_ordering
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def __eq__(self, other):
return self.age == other.age

def __lt__(self, other):
return self.age < other.age

p1 = Person("Алиса", 25)
p2 = Person("Боб", 30)

print(p1 < p2) # True
print(p1 <= p2) # True
print(p1 > p2) # False
print(p1 >= p2) # False

🔎В следующем посте рассмотрим ещё несколько функций

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🔥21
Продолжаем!

➡️cache: простая альтернатива lru_cache

Функция cache предоставляет простой способ кэширования результатов функции без ограничения размера кэша. Это может быть полезно, когда вы уверены, что количество уникальных входных данных ограничено.
from functools import cache

@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100)) # Мгновенный результат даже для больших чисел


➡️wraps: сохранение метаданных функции

Декоратор @wraps помогает сохранить метаданные оригинальной функции при создании декораторов. Это особенно важно при использовании инструментов документации и отладки.
from functools import wraps

def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""Это документация обертки"""
print("До вызова функции")
result = func(*args, **kwargs)
print("После вызова функции")
return result
return wrapper

@my_decorator
def say_hello(name):
"""Приветствует пользователя по имени"""
print(f"Привет, {name}!")

say_hello("Мария")
print(say_hello.__name__) # Выведет: say_hello
print(say_hello.__doc__) # Выведет: Приветствует пользователя по имени


🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43🔥2
✈️В Python все является объектом, даже сами классы. Это открывает перед нами удивительные возможности для создания динамических структур кода. Давайте погрузимся в мир создания классов и функций "на лету" с помощью type() и метаклассов.

➡️Магия функции type()

Функция type() в Python - это не просто инструмент для определения типа объекта. Она также может быть использована для создания новых классов динамически. Вот простой пример:
MyClass = type('MyClass', (), {'x': 42, 'my_method': lambda self: print("Hello!")})

obj = MyClass()
print(obj.x) # Выведет: 42
obj.my_method() # Выведет: Hello!

⬆️Здесь мы создали класс MyClass с атрибутом x и методом my_method. Удивительно, правда?

➡️Шаг вперед: метаклассы

Метаклассы - это классы классов. Они позволяют нам контролировать процесс создания классов. Рассмотрим пример:
class MyMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['additional_method'] = lambda self: print("I'm additional!")
return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMetaclass):
pass

obj = MyClass()
obj.additional_method() # Выведет: I'm additional!

⬆️В этом примере мы создали метакласс, который добавляет новый метод ко всем классам, использующим его.

➡️Практическое применение

Динамическое создание классов и функций может быть полезно в различных сценариях:
- Фабрики классов: создание классов на основе внешних данных или конфигурации.
- Декораторы классов: модификация классов без изменения их исходного кода.
- ORM (Object-Relational Mapping): динамическое создание классов на основе структуры базы данных.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍54🔥3
✈️В мире разработки программного обеспечения постоянно появляются новые тренды и подходы. Одним из таких трендов, набирающих популярность в последние годы, является функциональное программирование (ФП). Давайте разберемся, почему это происходит!

➡️Что такое функциональное программирование?

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

➡️Почему ФП становится популярнее?

💬Упрощение параллельного программирования: Отсутствие побочных эффектов делает код более предсказуемым и легким для распараллеливания.
💬Меньше багов: Неизменяемость данных и чистые функции снижают вероятность ошибок, связанных с состоянием программы.
💬Более читаемый код: ФП поощряет написание небольших, специализированных функций, что улучшает читаемость и поддерживаемость кода.
💬Легкость тестирования: Чистые функции легче тестировать, так как их поведение зависит только от входных данных.
💬Производительность: Некоторые функциональные концепции, такие как ленивые вычисления, могут повысить производительность программ.

➡️Заключение

Функциональное программирование становится все популярнее благодаря своим преимуществам в читаемости, тестируемости и параллельном выполнении. Хотя оно может потребовать некоторого времени для освоения, инвестиции в изучение ФП могут значительно улучшить качество вашего кода и эффективность разработки.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🔥2
👍5🔥41
Что выдаст код выше
Anonymous Quiz
12%
0
5%
1
37%
4
21%
5
8%
6
10%
10
6%
Error
👍7🤔7🤨3
🐍Разбор

Оператор continue используется в циклах для пропуска итерации в цикле.
Таким образом, пока а<4, у нас просто происходит увеличение этой переменной, а из-за условия, итерация (и код ниже) скипаются.
Далее у нас а станет равно 4. У нас не сработает ни один из if'ов и мы добавим это число 4 в result.
Ну и на след. итерации а == 5, у нас сработает break, который принудительно завершит цикл в той же строке.

Ответ: 4
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135🔥3
✈️Asyncio: ваш секретный ингредиент для высоких нагрузок

Представьте, что ваше приложение – это кухня в популярном ресторане. В синхронном мире у вас один шеф-повар, готовящий блюда по очереди. С asyncio у вас целая команда виртуозов, жонглирующих сковородками и готовящих несколько блюд одновременно. Вот это производительность!

➡️Настройка asyncio: тюнинг вашего кода

💬Выбор правильного event loop. Для Linux-систем рекомендую uvloop – он может разогнать ваше приложение до космических скоростей:
import asyncio
import uvloop

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())


💬Настройка пула потоков:
loop = asyncio.get_event_loop()
loop.set_default_executor(concurrent.futures.ThreadPoolExecutor(max_workers=10))


💬Семафоры — Они помогут контролировать конкурентность и избежать перегрузок:
sem = asyncio.Semaphore(10)

async def controlled_task(i):
async with sem:
# Ваш асинхронный код здесь
await asyncio.sleep(1)
print(f"Задача {i} выполнена!")


➡️Лайфхаки для покорения высот производительности

💬Замените requests на aiohttp для HTTP-запросов. Это как пересесть с велосипеда на реактивный самолет – скорость поразит ваше воображение!

💬Используйте aiomysql или asyncpg для работы с базами данных. Ваши запросы будут молниеносными, словно Усэйн Болт на стометровке!

💬Профилируйте код с помощью cProfile или yappi. Найдите узкие места и оптимизируйте их, как настоящий хирург производительности.

🔎Продвинутые техники

➡️Используйте асинхронные контекстные менеджеры для элегантной обработки ресурсов:
class AsyncContextManager:
async def __aenter__(self):
print("Entering the matrix...")
await asyncio.sleep(1)
return self

async def __aexit__(self, exc_type, exc, tb):
print("Exiting the matrix...")
await asyncio.sleep(1)

async def main():
async with AsyncContextManager() as manager:
print("We're in!")


➡️Не забывайте про асинхронные генераторы – они могут творить настоящие чудеса в потоковой обработке данных:
async def async_range(start, stop):
for i in range(start, stop):
await asyncio.sleep(0.1)
yield i

async def main():
async for num in async_range(0, 10):
print(num)


➡️Заключение: ваш путь к асинхронному совершенству

Asyncio – это не просто библиотека, это образ мышления. Освоив его, вы сможете создавать приложения, которые будут работать быстрее, эффективнее и элегантнее. Помните: в мире асинхронного программирования нет ничего невозможного!

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥43
Представьте, что ваш код – это оркестр в Мариинском театре. Каждый инструмент (поток или корутина) играет свою партию. А вы – дирижёр, который должен убедиться, что все звучит гармонично. Вот только как это сделать, когда все играют одновременно?

➡️1. Изоляция – ключ к успеху

Первое правило тестирования параллельного кода: изолируйте тесты! Каждый тест должен быть как отдельная комната в звукоизолированной студии. Используйте моки и стабы, чтобы симулировать внешние зависимости. Вот пример с использованием unittest.mock:
from unittest.mock import patch
import asyncio

async def fetch_data(url):
# Реальный запрос к API
...

@patch('your_module.fetch_data')
async def test_process_data(mock_fetch):
mock_fetch.return_value = {'key': 'value'}
result = await process_data('http://api.example.com')
assert result == 'processed value'


⬆️Мы изолировали тест от реального API. Теперь он быстрый, как Усэйн Болт, и предсказуемый, как восход солнца!

➡️2. Детерминизм – ваш лучший друг

Асинхронный код может быть непредсказуемым, как погода в Питере. Но ваши тесты должны быть стабильными, как гранитная набережная. Используйте семафоры, события и другие примитивы синхронизации, чтобы контролировать порядок выполнения. Вот пример с использованием asyncio.Event:
import asyncio

async def test_order_of_execution():
event = asyncio.Event()
results = []

async def task1():
await event.wait()
results.append(1)

async def task2():
results.append(2)
event.set()

await asyncio.gather(task1(), task2())
assert results == [2, 1]


⬆️Этот тест всегда будет проходить, даже если вы запустите его на компьютере, работающем на картофельной батарейке!

➡️3. Таймауты – не просто для пиццы

Установка таймаутов в тестах – это как страховка. Вы надеетесь, что она не понадобится, но лучше иметь ее под рукой. Вот как можно использовать таймауты в pytest:
import pytest
import asyncio

@pytest.mark.asyncio
async def test_long_running_task():
with pytest.raises(asyncio.TimeoutError):
await asyncio.wait_for(never_ending_task(), timeout=1.0)


⬆️Этот тест убедится, что ваша функция не зависнет, как старый Windows при запуске Crysis!

➡️4. Асинхронные фикстуры – ваш секретный козырь

В мире async/await фикстуры тоже должны быть асинхронными. Используйте async fixtures в pytest для подготовки и очистки тестового окружения. Вот пример:
import pytest
import asyncio

@pytest.fixture
async def database():
db = await create_database_connection()
yield db
await db.close()

@pytest.mark.asyncio
async def test_database_query(database):
result = await database.fetch('SELECT * FROM users')
assert len(result) > 0


⬆️Эта фикстура – как заботливая мама, которая готовит завтрак перед школой и убирает посуду после. Только вместо завтрака у нас база данных!

➡️5. Параллельное выполнение тестов – двойная выгода

Запуск тестов параллельно не только ускоряет процесс, но и помогает выявить проблемы с состоянием гонки. Используйте pytest-xdist, но будьте осторожны: убедитесь, что ваши тесты действительно независимы друг от друга. Вот команда для запуска:
pytest -n auto your_test_file.py


⬆️Это как устроить гонки Формулы-1 для ваших тестов. Победит самый быстрый и надежный код!

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43🔥3
✈️Docker - это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнеры позволяют упаковать приложение со всеми его зависимостями в стандартизированный блок для разработки программного обеспечения.

➡️Основы Docker

💬Образы (Images): Шаблоны для создания контейнеров
💬Контейнеры: Запущенные экземпляры образов
💬Dockerfile: Инструкции для сборки образа
💬Docker Hub: Репозиторий для хранения и обмена образами

➡️Базовые команды Docker:
# Сборка образа
docker build -t my-image .

# Запуск контейнера
docker run -d --name my-container my-image

# Просмотр запущенных контейнеров
docker ps

# Остановка контейнера
docker stop my-container


🔎Продвинутые техники

➡️1. Docker Compose

Docker Compose позволяет определять и запускать многоконтейнерные приложения. Пример docker-compose.yml файла:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"


➡️2. Docker Networking

Docker предоставляет мощные возможности для создания сетей между контейнерами:

💬Bridge networks: Стандартная сеть для контейнеров на одном хосте
💬Overlay networks: Для связи контейнеров на разных хостах
💬Host networking: Использование сети хоста напрямую

➡️3. Docker Volumes

Volumes используются для хранения данных вне контейнеров:
# Создание volume
docker volume create my-vol

# Использование volume при запуске контейнера
docker run -v my-vol:/app/data my-image


➡️4. Docker Swarm

Docker Swarm - это инструмент для оркестрации контейнеров, позволяющий управлять кластером Docker-хостов:

💬Инициализация Swarm: docker swarm init
💬Развертывание сервиса: docker service create
💬Масштабирование: docker service scale

➡️Лучшие практики

💬Используйте многоэтапные сборки для оптимизации образов
💬Минимизируйте количество слоев в Dockerfile
💬Используйте .dockerignore для исключения ненужных файлов
💬Регулярно обновляйте базовые образы для безопасности

➡️Заключение

Docker предоставляет мощный инструментарий для контейнеризации приложений, от простых сценариев до сложных микросервисных архитектур. Освоение Docker открывает новые возможности для разработки, тестирования и развертывания программного обеспечения.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍5🔥2🤣1
✈️Казалось бы, куда еще проще, но есть один интересный пакет JMESpath, который позволяет декларативно указать, как извлекать элементы из документа JSON.

➡️Основные примеры использования:
import jmespath

jmespath.search('foo.bar', {'foo': {'bar': 'baz'}})
# output: 'baz'

jmespath.search('foo.*.name', {'foo': {'bar': {'name': 'one'}, 'baz':
{'name': 'two'}}})
# output: ['one', 'two']

⬆️Тут нет ничего сложного. Метод search принимает паттерн, по которому требуется извлечь данные, а также словарь (который в общем-то похож на JSON).

➡️Возможностей у пакета достаточно, поэтому он достоен изучения и применения в проектах. Подробнее можно почитать в документации.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍65🔥4
✈️Сегодня поговорим о мощном инструменте, который может превратить вас в настоящего код-волшебника – Abstract Syntax Trees (AST). Если вы когда-нибудь задумывались, как работают линтеры, компиляторы или автоматические рефакторинг-инструменты, то добро пожаловать в увлекательный мир синтаксических деревьев!

🔎Представьте, что ваш код – это книга, а AST – её подробное содержание, где каждая глава, параграф и предложение аккуратно структурированы в древовидную форму. Каждый узел такого дерева представляет собой конструкцию вашего кода: функции, классы, операторы и даже отдельные переменные.

➡️В Python работа с AST стала намного проще благодаря встроенному модулю ast. Давайте разберем несколько практических примеров:

💬Базовый анализ кода:
import ast

code = """
def calculate_sum(a, b):
result = a + b
print(f"Sum: {result}")
return result
"""

# Создаем AST
tree = ast.parse(code)

# Анализируем структуру
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
print(f"Найдена функция: {node.name}")
elif isinstance(node, ast.Name):
print(f"Найдена переменная: {node.id}")


⬆️Этот простой пример показывает, как мы можем "гулять" по дереву AST и находить различные элементы кода. Это базовый строительный блок для создания более сложных анализаторов.

💬Трансформация кода:
class DebugTransformer(ast.NodeTransformer):
def visit_FunctionDef(self, node):
# Добавляем отладочный print в начало каждой функции
debug_print = ast.Expr(
value=ast.Call(
func=ast.Name(id='print', ctx=ast.Load()),
args=[ast.Constant(value=f"Вызов функции {node.name}")],
keywords=[]
)
)
node.body.insert(0, debug_print)
return node

# Применяем трансформацию
transformed = DebugTransformer().visit(tree)


⬆️Этот трансформер автоматически добавляет отладочный вывод в начало каждой функции. Представьте, насколько это удобно при отладке большого проекта!

💬Оптимизация кода:
class StringOptimizer(ast.NodeTransformer):
def visit_BinOp(self, node):
# Оптимизация конкатенации строк
if isinstance(node.op, ast.Add):
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
if isinstance(node.left.value, str) and isinstance(node.right.value, str):
return ast.Constant(value=node.left.value + node.right.value)
return node


⬆️Этот оптимизатор находит конкатенацию строковых литералов и объединяет их на этапе компиляции, что улучшает производительность.

➡️Вот несколько интересных применений AST в реальных проектах:

- Статический анализ безопасности: поиск потенциальных уязвимостей в коде
- Автоматическая документация: генерация документации на основе структуры кода
- Миграция кода: автоматическое обновление устаревших конструкций
- Оптимизация производительности: автоматический поиск неэффективных паттернов

➡️Продвинутый пример: Давайте создадим анализатор сложности кода:
class ComplexityAnalyzer(ast.NodeVisitor):
def __init__(self):
self.complexity = 0

def visit_If(self, node):
self.complexity += 1
self.generic_visit(node)

def visit_For(self, node):
self.complexity += 2
self.generic_visit(node)

def visit_While(self, node):
self.complexity += 2
self.generic_visit(node)

# Использование
analyzer = ComplexityAnalyzer()
analyzer.visit(tree)
print(f"Сложность кода: {analyzer.complexity}")


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

- Работа с типами данных и аннотациями через AST
- Создание собственных декораторов с помощью трансформации AST
- Оптимизация циклов и условных конструкций
- Анализ потока данных в программе

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73🔥3
✈️Serverless архитектура — это модель вычислений в облаке, где разработчики пишут код, а провайдер облачных услуг управляет серверами. Это позволяет сосредоточиться на разработке, не думая о серверной инфраструктуре.

👀Преимущества Serverless Архитектуры:
- Снижение затрат: Платите только за фактическое использование ресурсов, что часто приводит к экономии средств.
- Масштабируемость: Автоматическое масштабирование помогает справляться с любыми нагрузками без необходимости в ручном управлении.
- Упрощение DevOps: Нет необходимости управлять серверами и их конфигурацией.

⭐️Недостатки Serverless Архитектуры:
- Холодный старт: Время, необходимое для инициализации функции, может быть значительным и влиять на производительность.
- Ограничения исполнения: Функции могут иметь ограничения по времени выполнения и памяти, что может быть проблематично для более сложных задач.
- Зависимость от провайдера: Использование специфичных для провайдера технологий может привести к привязке к одному облаку.

➡️Заключение

Serverless архитектура предоставляет мощный инструмент для современных разработчиков, предлагая значительную экономию времени и ресурсов. Однако, важно учитывать её ограничения при выборе данной модели для своего проекта.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥4👍3
🦆Duck typing — это концепция, позволяющая использовать объекты независимо от их типа, базируясь на их свойствах и методах. Основная идея — не проверять тип объекта напрямую, а пытаться использовать его так, как нам нужно.

👀Преимущества:
—Нет необходимости привязываться к конкретным классам и типам.
—Код становится более гибким и менее связанным.
—Легче расширять и изменять код, добавляя новые типы.
—Упрощает полиморфизм.

➡️Пример кода:
class Bird:
def fly(self):
return "I can fly!"

class Duck(Bird):
def quack(self):
return "Quack!"

class Airplane:
def fly(self):
return "I can also fly!"

def make_it_fly(flyable_thing):
print(flyable_thing.fly())

# Создаем объекты
duck = Duck()
airplane = Airplane()

# Используем их, не смотря на разные типы
make_it_fly(duck) # Выведет: I can fly!
make_it_fly(airplane) # Выведет: I can also fly!

⬆️В этом примере функция make_it_fly принимает любой объект, который имеет метод fly(). Если объект соответствует этому интерфейсу, он будет выполнен, независимо от того, является ли объект уткой, самолетом или чем-то еще.

🔎Duck typing позволяет создавать более гибкий и динамичный код, так как вы можете использовать объекты, которые соответствуют необходимым интерфейсам, не заботясь о их конкретных классах.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94🔥3🤣1
✈️Whylogs - это библиотека для логирования и анализа данных в Python. Она предназначена для легкого отслеживания метрик данных, которые могут помочь в мониторинге и улучшении производительности моделей машинного обучения. Почему это важно? Потому что понимание ваших данных и способов их изменений со временем может существенно повлиять на качество моделей.

➡️Основные функции Whylogs:
—Автоматическое извлечение метрик: Библиотека собирает метрики, такие как распределения, статистики и т.д.
—Поддержка различных форматов данных: Логирование можно выполнять для различных источников данных, включая Pandas DataFrames и потоковые данные.
—Интеграция с другими инструментами: Whylogs легко интегрируется с другими библиотеками и фреймворками.

➡️Пример использования Whylogs:
import whylogs as why
import pandas as pd

# Создание примера данных
data = {
"age": [25, 30, 35, 40, 45],
"income": [50000, 60000, 70000, 80000, 90000]
}
df = pd.DataFrame(data)

# Инициализация логгера
logger = why.logger()

# Логируем данные
logger.log_dataframe(df)

# Генерируем отчет
report = logger.report()

# Сохраняем отчет
report.save("report.whylog")

# Выводим на экран
print(report)

⬆️В этом примере мы создаем DataFrame с двумя колонками: age и income. Затем мы инициализируем Whylogs логгер, логируем наш DataFrame, генерируем и сохраняем отчет.

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

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4🔥2
✈️Конструкция raise используется для генерации исключений. Когда в коде происходит что-то непредвиденное или некорректное — можно сгенерировать исключение командой raise.

➡️Основные моменты конструкции raise:
—Возбуждение существующих исключений: Вы можете использовать raise без каких-либо параметров в блоке except, чтобы повторно вызвать текущее исключение.
—Создание собственных исключений: Вы можете создать или вызвать собственное исключение, создав объект исключения и передав его в raise.

➡️Пример использования raise:

def divide(a, b):
if b == 0:
raise ValueError("Деление на ноль невозможно.")
return a / b

try:
result = divide(10, 0)
except ValueError as e:
print(f"Ошибка: {e}")

⬆️В этом примере функция divide вызывает исключение ValueError, если второй аргумент равен нулю. В блоке try мы пытаемся выполнить деление, и если возникает ошибка, мы перехватываем её и выводим сообщение об ошибке.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83🔥3
✈️Сегодня поговорим о крутой фиче Python, которая может значительно сократить потребление памяти вашими объектами. Речь пойдёт об атрибуте slots!

➡️Для начала давайте разберемся, почему вообще возникла необходимость в slots. По умолчанию Python хранит атрибуты объектов в специальном словаре dict. Это удобно и гибко – можно добавлять новые атрибуты на лету. Но у такой роскоши есть цена: дополнительные накладные расходы на память.

🔎Представьте, что у вас миллион объектов класса User с парой атрибутов. Каждый такой объект тащит за собой словарь dict, а это прожорливая структура данных. И тут на сцену выходит наш герой – slots!

# Без slots
class User:
def __init__(self, name, age):
self.name = name
self.age = age

# Со slots
class OptimizedUser:
__slots__ = ['name', 'age']

def __init__(self, name, age):
self.name = name
self.age = age


➡️Что даёт нам slots? Вместо создания словаря Python выделяет фиксированный массив в памяти под указанные атрибуты. Это как переход от просторного лофта к компактной студии – места меньше, зато экономия налицо!

➡️Реальные цифры? На практике использование slots может сократить потребление памяти на 30-50% для простых объектов. А при работе с миллионами инстансов экономия становится более чем существенной.

➡️Где это реально пригодится:
—В больших датасетах, где у вас тысячи/миллионы однотипных объектов
—В микросервисах, где важна оптимизация памяти
—В системах реального времени, где каждый байт на счету
—В долгоживущих процессах, обрабатывающих потоки данных

➡️Подводные камни:
—Нельзя добавлять новые атрибуты после определения класса
—Наследование работает не так прозрачно, как с обычными классами
—Некоторые метаклассы могут конфликтовать со slots

➡️Пример реального применения:
class DataPoint:
__slots__ = ['timestamp', 'value', 'sensor_id']

def __init__(self, timestamp, value, sensor_id):
self.timestamp = timestamp
self.value = value
self.sensor_id = sensor_id

# Представьте, что таких объектов у вас миллионы
data_points = [DataPoint(time.time(), random.random(), i) for i in range(1_000_000)]


🔎Про что стоит помнить: slots – это не волшебная таблетка. Используйте его там, где действительно важна оптимизация памяти и где вы уверены в неизменном наборе атрибутов.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥54
✈️Конструкция if __name__ == '__main__' используется для того, чтобы определить, запущен ли файл модуля напрямую или импортирован из другого модуля.

➡️Простой пример:
def main():

# Точка входа в программу
if __name__ == '__main__':
main()


➡️Эта конструкция позволяет запустить какой-нибудь код только при прямом вызове модуля, так как name будет равно 'main' только если модуль запущен напрямую.

➡️Это позволяет запускать программу полностью только когда она основная, а не импортируется в качестве модуля.

🐍Pythoner
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥4👍3