Отчет Pylance UnknownMemberType, хотя тип переменной известен

Я использую Pylance в VSCode и получаю это предупреждение / ошибку reportUnknownMemberType для этой переменной, хотя я вижу, что она знает тип.

Я новичок в занятиях, поэтому, если есть способ сделать это лучше, дайте мне знать. Моя цель - расширить родительский класс dict еще несколькими ключами в подклассе. Программа действительно работает, родительский dict получает новую пару ключей и значений, но я хочу знать, почему я получаю ошибку Pylance.

Ниже приводится цепочка наследования этих классов, имена упрощены, но структура настоящая. Участвуют 3 класса, наследующие как Base> SubClass> SubSubClass. Базовый класс находится в отдельном файле:

      #base.py
     
class Base:
    def __init__(self, param0: str) -> None:
        self.param0 = param0
        self.exportable = dict[str, object]()        
 

Два других класса находятся во втором файле:

      # subclasses.py

class SubClass(Base):
    def __init__(self, param0: str, param1: str, param2: str, 
                     param3: str, param4: str, 
                     param5: bool=True) -> None:
        super().__init__(param0)
    
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3
        self.param4 = param4
        self.param5 = param5

        self.exportable = {
            self.param0: {
                'param1': self.param1,
                'param2': self.param2,
                'param3': self.param3,            
                'param4': self.param4,
                'param5': self.param5
            }
        }


class SubSubClass(SubClass):
    def __init__(self, param1: str, param3: str) -> None:        
        super().__init__(name='hardcodedparam0', param1=param1, type='hardcodedparam2', param3=param3, 
                param4='hardcodedparam4')

    self.properties = {
        'name': {
            'type': "string"
        },
        'contentBytes': {
            'type': 'string',
            'format': 'byte'
        }
    }

    # this is where I get the error
    new_exportable = self.exportable.copy()
    self.exportable = {**new_exportable, **self.properties}

Мой первоначальный план состоял в том, чтобы просто использовать self.exportable[self.name]['properties'] = self.propertiesвместо этого слияния dict, но я получаю, что это не может назначить ошибку.

Я также попытался в SubSubClass получить доступ к SubClass с помощью super().exportable, хотя я не думаю, что это необходимо, но когда я запускаю программу, я получаю сообщение об ошибке, говорящее, что super() не имеет атрибута 'exportable' . Как бы то ни было, это super() попытка также дает ту же ошибку «невозможно назначить», указанную выше, когда программа не запущена.

С первым вариантом (слияние dict) и вторым вариантом (назначение нового ключа свойств и значения) программа работает и self.properties dict успешно прикреплен к унаследованному self.exportableдикт. Но я хочу знать, все ли я делаю что-то не так, или Пилэнс просто запутался. Я думаю, это сбивает с толку, потому что в SubClass он видел, что dict был просто dict[str,Union[str,bool]] но затем подкласс B, вместо этого Union[str,bool] значение, пытается добавить properties dict, который является самим набором dict?

Конечно, я могу просто отключить ошибку reportUnkownMemberType в конфигурации Pylance, но меня беспокоит, что я маскирую то, о чем я не знаю.

Спасибо

1 ответ

Думаю, я решил эту проблему, проявив большую гибкость с помощью экспортируемого SubClass. То есть создание пустого dict, привязка начальных свойств и привязка в SubSubClass любых дополнений:

      # subclasses.py

class SubClass(Base):
    def __init__(self, param0: str, param1: str, param2: str, 
                     param3: str, param4: str, 
                     param5: bool=True) -> None:
        super().__init__(param0)
    
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3
        self.param4 = param4
        self.param5 = param5

        # The following two lines are a bit different
        self.exportable = {}
        self.exportable[self.param0] = {
            'param1': self.param1,
            'param2': self.param2,
            'param3': self.param3,            
            'param4': self.param4,
            'param5': self.param5
        }
 


class SubSubClass(SubClass):
    def __init__(self, param1: str, param3: str) -> None:        
        super().__init__(name='hardcodedparam0', param1=param1, type='hardcodedparam2', param3=param3, 
                param4='hardcodedparam4')
        self.properties = {
            'name': {
                'type': "string"
            },
            'contentBytes': {
                'type': 'string',
                'format': 'byte'
            }
        }

        # Now I can assign a key and value with no Pylance error
        self.exportable[self.name]['properties'] = self.properties

Кажется, разница между

  • Установка начального экспортируемого словаря как имеющего фиксированный ключ () и значение (вложенный param1, param2, param3, так далее.)
  • Установка исходного экспортируемого объекта как пустой dict, присвоение param0 ключ и значение, а затем в SubSubClass просто присваивая новое значение ключа

Я не уверен, что это просто обходной путь, если мне просто удается обмануть Pylance, чтобы он не соглашался, или это реальное решение. В любом случае я больше не получаю ошибки Pylance, и программа (по-прежнему) работает.

Другие вопросы по тегам