#python #python-typing #python-dataclasses
Вопрос:
Я пытаюсь в основном сделать это:
@dataclass
class A:
pass
@dataclass
class B(A):
pass
@dataclass
class container:
stuff: List[A OR B OR any future defined child class]
Единственный способ, который я нашел, посмотрев здесь и на странице PEP484, кажется, выглядит примерно так…за исключением того, что он не работает
thing_co = TypeVar('thing_co', covariant=True)
class ListOfAOrLower(List[thing_co ]):
pass
@dataclass
class container:
stuff: ListOfAOrLower
Когда я пытаюсь создать свой контейнер (т. Е. «контейнер([B()])»), pylance в vscode говорит, что типы несовместимы. Когда я пытаюсь сказать, что «вещи» — это список[thing_co], пиланс сообщает, что «Тип «thing_co» не имеет значения в этом контексте».
Я чувствую, что то, что я пытаюсь сделать, глупо просто, и все же я не могу заставить средство проверки типов принять эту довольно стандартную формулировку. Кто-нибудь может подсказать, как подчинить проверку типов моей воле? Спасибо
Комментарии:
1. Есть ли причина
stuff: List[A]
, по которой этого недостаточно? Насколько я помню, утверждения типа по умолчанию являются ковариантными, поэтому проверка типов должна принимать любой подклассA
. Вы также можете использоватьmypy
для подтверждения правильности, возможно, это ошибка в pylance.2. Это может быть ошибка, это хороший момент. Я посмотрю, не поступало ли каких-нибудь сообщений. Я использую pylance, потому что он, по моему опыту, в 1000 раз лучше во всем остальном. Список[А] определенно не сработал, это то, что я предполагал, было бы нормально, и он суетился. Правка: это может быть взаимодействие с тем, как работает декоратор классов данных. Может быть, я просто создам этот класс вручную.
3. Список инвариантен , потому что он может быть как записан, так и прочитан. Не имеет смысла, чтобы список содержал «классы A или дочерние», и если вы принудите его к этому, это может привести к появлению тонких ошибок. Вы намеревались сделать
container
общий над каким-то конкретным подклассомA
?4. Так что, похоже, это действительно была проблема с классом данных. Просто сделал его классом данных с определенной пользователем функцией инициализации, и подсказки типа были приняты.
5. @MisterMiyagi я не совсем понимаю. Чтобы, возможно, упростить это, у меня есть глупо простой файл excel, который я загружаю, поэтому мне не нужно беспокоиться о создании реального пользовательского интерфейса для этого приложения, и у меня в основном 2 формата файлов с небольшими различиями. В версии A есть столбцы X, Y, Z. В версии B есть W,X,Y,Z. Поэтому я хочу иметь универсальную функцию для загрузки этого, но фактический потребитель знает, ожидает ли он данные A или B. Я просто хочу, чтобы грузчик не знал. В принципе, я не хочу копировать-вставлять одни и те же 10 строк кода openpyxl 🙂
Ответ №1:
Проблема для меня заключалась в том, что пиланс взаимодействовал с декоратором классов данных. Это было решено путем указания моей собственной функции инициализации.