Подсчет используемых атрибутов во время выполнения - PullRequest
0 голосов
/ 03 июля 2018

Я работаю над проектом Python, который требует от меня компиляции определенных атрибутов некоторых объектов в набор данных. Код, который я сейчас использую, выглядит примерно так:

class VectorBuilder(object):
    SIZE = 5

    def __init__(self, player, frame_data):
        self.player = player
        self.fd = frame_data

    def build(self):
        self._vector = []

        self._add(self.player)
        self._add(self.fd.getSomeData())
        self._add(self.fd.getSomeOtherData())

        char = self.fd.getCharacter()
        self._add(char.getCharacterData())
        self._add(char.getMoreCharacterData())

        assert len(self._vector) == self.SIZE
        return self._vector

    def _add(self, element):
        self._vector.append(element)

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

Я подумал о том, чтобы вместо этого сохранить список всех функций, использованных для построения набора данных в виде строк (как в attributes = ['getPlayer', 'fd.getSomeData', ...]), а затем определить функцию build как что-то вроде:

def build(self):
    self._vector = []
    for att in attributes:
        self._vector.append(getattr(self, att)())
    return self._vector

Это позволило бы мне получить доступ к размеру просто как len(attributes), и мне нужно всего лишь отредактировать attributes, но я не знаю, как заставить этот подход работать с связанными вызовами функций, такими как self.fd.getCharacter().getCharacterData().

Есть ли более чистый способ выполнить то, что я пытаюсь сделать?

EDIT:

Требуется дополнительная информация и пояснения.

  1. Я использовал __ из-за какого-то дурного совета, который я прочитал в Интернете (по сути, я сказал, что я должен использовать _ для членов, закрытых для модуля, и __ для членов класса, закрытых). Я отредактировал их для _ атрибутов.
  2. Геттеры являются частью фреймворка, который я использую.
  3. Вектор хранится как закрытый член класса, поэтому мне не нужно передавать его методам конструирования, которые на самом деле более многочисленны, чем простой _add, делая некоторые другие вещи, такие как нормализация и bool->int преобразование на элементы перед добавлением их в вектор.
  4. SIZE в том виде, в каком оно существует в данный момент, является истинной константой. Ему дается только значение в первой строке VectorBuilder, и оно никогда не изменяется во время выполнения. Я понимаю, что не разъяснил это должным образом в основном посте, но новые атрибуты никогда не добавляются во время выполнения. Корректировка, о которой я говорил, будет происходить во время программирования. Например, если бы я хотел добавить новый атрибут, мне нужно было бы добавить его в функцию build, например ::

    self._add(self.fd.getCharacter().getAction().getActionData().getSpeed())
    

    , а также измените определение SIZE на SIZE = 6.

  5. Атрибуты компилируются в то, что в настоящее время представляет собой простой список Python (но, вероятно, будет заменен массивом с нулями), а затем передаются в нейронную сеть в качестве входного вектора. Однако сама нейронная сеть должна быть построена в первую очередь, и это происходит до того, как какие-либо данные становятся доступными (то есть до создания любых входных векторов). Однако для успешного построения нейронной сети необходимо знать размер входных векторов, которые она будет получать. Вот почему необходим SIZE, а также причина утверждения assert - чтобы удостовериться, что векторы, которые я передаю в сеть, на самом деле соответствуют размерам, которые, как я утверждал, я передаю ей.

Я знаю, что код не пифоничен, поэтому я здесь - код работает, он просто уродлив.

1 Ответ

0 голосов
/ 04 июля 2018

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

Ваша переменная SIZE будет по-прежнему иметь длину динамического списка аргументов, предоставленного, например, в build(self,*args).

...