Pythonic способ подклассификации списка - PullRequest
0 голосов
/ 22 мая 2018

Вот мое общее проблемное пространство:

У меня есть протокол байтов / битов с устройством через I2C.

У меня есть "база данных" команд, чтобы полностью описать всеТипы битовых полей, значения и перечисления.

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

MyProtocol = Protocol('database.xml',I2CDriver())
theStatus = MyProtocol.GET_STATUS()

создает правильныепоток байтов для команды GET_STATUS, отправляет ее через i2c и возвращает ответ в виде байтового массива в настоящее время.Я могу заставить его печатать ответ внутри реализации GET_STATUS (), но я хочу переместить это поведение в возвращаемый объект, а не в команду.

Я хочу, чтобы мой возвращаемый объект был «умным»: theStatus должен иметь список / массив байтов плюс ссылку на определения его полей.

Я хочу, чтобы theStatus действовал как список / байтовый массив, поэтому я могу напрямую проверять байты.Мне все равно, если слайсы - это что-то кроме списков байтов или байтов.Как только они вырезаны, они просто байты.

Я хочу, чтобы «theStatus» можно было печатать print(theStatus), и он должен был печатать все поля в статусе.Мне удобно, как это сделать, когда я остановлюсь на работоспособной структуре данных, которая позволяет мне получить доступ к байтам и базе данных.

Я хочу проверить theStatus по имени поля с чем-то вроде theStatus.FIELDNAME или, может быть theStatus['FIELDNAME']'.То же самое: если у меня есть работоспособная структура данных, в которой байтовый массив и база данных являются членами, я могу сделать это.

Проблема в том, что я не знаю, какая "правильная" структура данных вызывает наименьшее количествоколичество проблем.

Какие-нибудь предложения о наиболее питонском способе сделать это?Сначала я хотел создать подкласс list и добавить определения полей в качестве члена, но кажется, что python вообще не нравится эта идея.

Композиция выглядит как следующая ставка, но заставляет ее действоватькак правильный list кажется, что это может быть куча работы, чтобы сделать это 'правильно'.

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Что вам действительно нужно, так это реализовать новую последовательность типа , возможно, изменяемую.Вы можете либо создать его с нуля, реализовав специальные методы, необходимые для эмуляции типов контейнеров , либо использовать в качестве основы подходящую collections.abc коллекцию ABC .

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

Например, (неизменяемый) Sequence ABC требует от вас только предоставления реализаций для __getitem__ и __len__;базовая реализация ABC предоставляет остальное:

from collections.abc import Sequence

class StatusBytes(Sequence):
    def __init__(self, statusbytes):
        self._bytes = statusbytes

    def __getitem__(self, idx_or_name):
        try:
            return self._bytes[idx_or_name]
        except IndexError:
            # assume it is a fieldname
            return FIELDNAMES[idx_or_name]

    def __len__(self):
        return len(self._bytes)

Если вам действительно нужна реализация полного списка, включая поддержку расширенных сравнений (list_a <= list_b), сортировки (list_a.sort()), копирования [list_a.copy()]и умножение (list_a * 3), то есть также collections.UserList() класс .Этот класс наследует от collections.abc.MutableSequence и добавляет дополнительные функциональные возможности, которые list предлагает по сравнению с ABC базовой последовательности.Если вам не нужна эта дополнительная функциональность, придерживайтесь базовых ABC.

0 голосов
/ 22 мая 2018

Похоже, вы ищете collection.UserList .

0 голосов
/ 22 мая 2018

Создайте подкласс, который наследуется от collections.UserList, это именно то, что для https://docs.python.org/3/library/collections.html#collections.UserList

...