У меня есть общий класс данных, который содержит два массива 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 выдаст ошибку, но при построении ничего не происходит. В результате мне нелегко найти, где именно я построил объект неправильного размера.
Если бы размер был проверен при построении, вместо этого было бы выброшено исключение, и я сразу же смогу обнаружить проблему.
Конечно, я мог бы проверить каждый экземпляр 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
Код: Выделить всё
@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,)
Подробнее здесь: https://stackoverflow.com/questions/784 ... n-purposes