Проблема здесь двоякая:
- PyCharm имеет немного слепое пятно (на момент написания) в отношении правильной обработки метаклассов с помощью ввода. Поэтому без дополнительных «подсказок» он не может вывести правильный тип для
value
в настоящее время. - Поскольку вы инициализировали свой список с помощью
None
PyCharm обрабатывает его как список, содержащий Nones.
Давайте начнем с проблемы метакласса:
Вы проверяете, является ли data_type
классом, проверяя, является ли он экземпляром type
(метакласс классов по умолчанию). Затем вы проверяете, является ли value
экземпляром класса. Это нормально.
Однако PyCharm предполагает, что ваш data_type
является type
(что правильно), но после isinstance(value, self._data_type)
он также предполагает, что value
является type
(что неправильно -он должен быть типа _data_type
). Так что просто используя assert isinstance(...)
с data_type
и value
PyCharm не сможет определить правильный тип value
!
Так что это, вероятно, квалифицируется как ошибка или отсутствующая функция в PyCharm - илив любой библиотеке, используемой PyCharm для определения типов.
Вторая проблема заключается в том, что при инициализации _data
с помощью None
PyCharm выведет тип _data
как List[None]
(aсписок, содержащий Nones).
Так что, если PyCharm выводит что-либо, кроме Any
(который может быть назначен на что угодно) или None
(который будет ожидаемым типом содержимого списка) для value
, это будетвыдает предупреждение.
Даже при:
def set_field(self, index, value):
assert isinstance(value, int) # <-- difference
assert isinstance(index, int)
self._data[index] = value
Придет предупреждение.
На данный момент у вас есть два варианта:
- Игнорировать предупреждение.
- Использовать полноценные подсказки типов (если целевые версии Python допускают это).
Если вы хотите использовать подсказку по типу, вы можете, например, использовать:
from typing import List, Optional, TypeVar, Generic, Type
T = TypeVar('T')
class Data(Generic[T]):
_data: List[Optional[T]]
_data_type: Type[T]
def __init__(self, length: int, data_type: Type[T]):
self._data = [None] * length
self._data_type = data_type
def set_field(self, index: int, value: T):
if isinstance(value, self._data_type):
self._data[index] = value
raise TypeError()
Примечание: я полностью удалил утверждения. Если аргументы не имеют ожидаемого типа или значения, TypeError
или ValueError
будут более информативными. Однако в большинстве случаев документация и / или подсказки типов могут адекватно заменить assert
s, а также TypeError
s в Python (по крайней мере, на IDE или при использовании mypy).