Параметризация аннотации типа в классе данных для целей проверки.Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Параметризация аннотации типа в классе данных для целей проверки.

Сообщение Anonymous »

Проблема
У меня есть общий класс данных, который содержит два массива numpy:

Код: Выделить всё

@dataclass
class VectorCovariancePair:
data: np.ndarray[np.float64] # expected size: N
covariance: np.ndarray[np.float64] # expected size: N * N
Некоторые другие классы используют это для представления значений разных размеров, например:

Код: Выделить всё

@dataclass
class Pose:
position: VectorCovariancePair # expected size: 3
orientation: VectorCovariancePair # expected size: 4

# ... and other classes ...
Каждый из них имеет метод, который я использую для создания соответствующего сообщения. Здесь конструктор сообщения проверяет размер вектора и выдает ошибку. Я заменю его утверждением.

Код: Выделить всё

class Pose:
# ...
def to_msg(self):
assert self.position.data.size == 3
msg = # ...
return msg
Моя программа структурирована таким образом, что я создаю объект в модуле и использую to_msg в совершенно другом модуле.
Теперь я построил некоторые из этих объектов неправильно размер; to_msg выдаст ошибку, но при построении ничего не происходит. В результате мне нелегко найти, где именно я построил объект неправильного размера.
Если бы размер был проверен при построении, вместо этого было бы выброшено исключение, и я сразу же смогу обнаружить проблему.
Конечно, я мог бы проверить каждый экземпляр VectorCovariancePair непосредственно в классах, которые их используют:

Код: Выделить всё

class Pose:
# ...
def __post_init__(self):
assert self.position.data.size == 3
assert self.orientation.data.size == 4
но это приведет к большому количеству шаблонного и повторяющегося кода.
Моя попытка
Я пробовал чтобы имитировать то, что я бы сделал на C++, и просто привязать к классу общий параметр. Я посмотрел, как использовать typing.Generic, и придумал следующее:

Код: Выделить всё

from typing import TypeVar, Generic

N = TypeVar('N', bound=int)

@dataclass
class VectorCovariancePair(Generic[N]):
# ...
def __post_init__(self):
n = retrieve_N(self)
assert self.data.size == n
assert self.covariance.size == n * n
В результате получится очень элегантный код с проверкой, расположенной исключительно в VectorCovariancePair:

Код: Выделить всё

@dataclass
class Pose:
position: VectorCovariancePair[3]
orientation: VectorCovariancePair[4]
К сожалению, мне не удалось получить аргумент. Я попробовал оба варианта, но результат один и тот же:

Код: Выделить всё

def retrieve_n(obj):
print(obj.__orig_bases__[0].__args__) # (~N,)
print(typing.get_args(obj.__orig_bases__[0])) # (~N,)
Я предполагаю, что причина в том, что эта информация не содержится в экземплярах VectorCovariancePair. Как бы вы подошли к этой проблеме?


Подробнее здесь: https://stackoverflow.com/questions/784 ... n-purposes
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»