Разница между List[Optional[str]] и Iterable[str]
Установил mypy и при анализе строчки кода ",".join(ids[:50])
ids: List[Optional[str]] = ["text","test"]
error: Argument 1 to "join" of "str" has incompatible type "List[Optional[str]]"; expected "Iterable[str]"
Почему это ошибка? Разве список не итерируемый объект? Какая разница между списком и Iterable и в каких случаях что выбирать?
Ответы (2 шт):
В качестве ответа вопрос:"Какая разница между списком и Iterable и в каких случаях что выбирать?" можно привести пример,
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
for x in myclass:
print(x)
В результате выполнения мы получим числа от 1 до 20. myclass является итерируемым объектом, в то же время он генерирует свои значения во время исполнения, в отличие от списка который всегда сформирован. Список имеет в себе итератор, как и строка, они возвращают его с помощью метода iter() таким образом мы получаем разницу между списком и итератором:
list != iter(list)
Проблема не в List/Iterable, а в Optional. List[Optional[str]] подразумевает то, что список может содержать строки или None, но join не умеет соединять значения None, требуемый тип принимаемого значения у него - Iterable[str], т.е. итерируемый объект из строк (строго из строк, никаких None). Если убрать Optional, то ошибка исчезнет.
Пример кода:
from typing import List
ids: List[str] = ["text","test"]
print(", ".join(ids))
Вывод mypy:
Success: no issues found in 1 source file
mypy на Optional ругается не просто так: ваша аннотация предполагает, что возможен список такого вида ["text", None], при применении join к которому вылетит ошибка TypeError: sequence item 1: expected str instance, NoneType found.