Skip to content

Питонические рецепты и наброски, рассматривающие задачу и способ её решения с помощью средств языка 🧐

Notifications You must be signed in to change notification settings

frozzway/python-recipes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Recipe #1 - Logger

Имеется структура-абстракция Array и её отстортированный вариант SortedArray. Чтобы проверить работу поддерживаемых этими структурами методов, хотелось бы видеть состояние массива на момент 'до' и 'после' выполнения определенной операции: количество элементов, остаток памяти и т.д.

Был написан декоратор, который переопределяет все открытые методы класса, добавляя к ним функцию логирования в файл/системный поток с отображением стека инкапсулированных подвызовов. Такой декоратор независим от класса-структуры, к которой применяется. Добавление поддержки логирования требует понимания способа декорирования, инспекции методов, областей видимости. Алгоритм поддерживает один подуровень: подвызовы подвызовов останутся на одном уровне, но этого достаточно. Стек вызовов записывается в очередь.

@enable_logging(stdout)
class SortedArray(Array):
    def random_fill(self):
        super(self.__class__, self).random_fill()
        self.selection_sort()
# ...

arr = SortedArray(5)  
arr.random_fill()

записывает следующие логи

 → Called <SortedArray>.random_fill()
   Before: [None, None, None, None, None] top=0, size=5
   After: [17, 19, 54, 76, 79] top=4, size=5

     ↳ Called <SortedArray>.random_fill(), base method of <Array>
       Before: [None, None, None, None, None] top=0, size=5
       After: [79, 19, 17, 54, 76] top=4, size=5

     ↳ Called <SortedArray>.selection_sort(), base method of <Array>
       Before: [79, 19, 17, 54, 76] top=4, size=5
       After: [17, 19, 54, 76, 79] top=4, size=5

Семантика Python: специальные методы, декорирование, инспектирование во время выполнения, области видимости.
Алгоритмы и структуры: абстракция Array, SortedArray и их методов, алгоритм сортировки, симуляция выделяемой памяти.

Recipe #2 - Dynamic attributes and properties

Необходимо воспользоваться динамическими атрибутами для обработки данных в формате JSON. Пусть имеется набор данных следующей структуры:

{ "Schedule": {
    "events": [{ 
        "serial": 33451,
        "name": "Migrating to the Web Using Dart and Polymer - A Guide for Legacy OOP Developers",
        "website_url": "http://oscon.com/oscon2014/public/schedule/detail/33451",
        "speakers": [ 149868 ],
      }],
    "speakers": [{
        "serial": 149868,
        "name": "Faisal Abid",
      }]
}}

JSON-объект с ключом Schedule содержит отображение с ключами events и speakers, за каждым из которых находится ассоциированный список записей с уникальным идентификатором serial. Каждая запись мероприятия содержит список докладчиков (их идентификаторы).

Мероприятия и докладчики десериализованы в объекты соответствующих классов Event и Speaker. Обращения к полям events осуществляются через одноименные атрибуты объекта. Например для чтения адреса веб-страницы мероприятия вызывается <Event>.website_url. Вызов атрибута <Event>.speakers возвращает список объектов Speaker для мероприятия.

col = DataCollection('text.json')
event: Event = col.events['event.33597']
speakers: list[Speaker] = event.speakers
print(f'Event: {event}, url: {event.website_url}\nSpeakers: {speakers}')
Event: <Event: Quantifying your Fitness>, url: http://oscon.com/oscon2014/public/schedule/detail/33597
Speakers: [<Speaker: Kirsten Hunter>, <Speaker: Kjerstin Williams>]

Recipe #3 - Async TCP socket server

Асинхронный TCP сокет сервер asyncio.start_server(), получающий сообщения от клиентов и записывающий их в файл.

Для каждого нового соединения вызывается callback, который принимает в качестве аргументов StreamReader и StreamWriter. Непрерывно считывает фрагменты поступающих байт с помощью <StreamReader>.readline(), преобразует каждый фрагмент в строку и записывает его в файл, открывая для этого новый поток с помощью futures.ThreadPoolExecutor(). При получении пустой строки закрывает соединение. В ответ на сообщение "LIST", считывает все записанные сообщения из файла и отправляет клиенту.

Обработка подключения к адресам ('192.168.56.1', 8088), ('192.168.0.150', 8088)
Открыл соединение для клиента ('192.168.0.150', 59795)
Сохранил сообщение "Message 1" от клиента ('192.168.0.150', 59795)
Сохранил сообщение "Message 2" от клиента ('192.168.0.150', 59795)
Открыл соединение для клиента ('192.168.0.150', 59805)
Сохранил сообщение "Message 3" от клиента ('192.168.0.150', 59805)
Сохранил сообщение "Message 4" от клиента ('192.168.0.150', 59795)
Отправил список сообщений клиенту ('192.168.0.150', 59795).
Закрыл соединение для клиента ('192.168.0.150', 59795)

На заметку: ThreadPoolExecutor можно заменить на asyncio.to_thread()

About

Питонические рецепты и наброски, рассматривающие задачу и способ её решения с помощью средств языка 🧐

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages