подсказка типа python для класса и детей в классе композиции

#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:

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