Я немного озадачен аннотациями типов в python3, особенно для функции генератора, которая выплевывает сгенерированные типы. Я думаю, что именно моя путаница проистекает из документации typing.Type
. Вот мой фрагмент кода:
from collections import UserList
UserType = TypeVar('UserType')
def TypeSequence(usertype: Type[UserType]) -> Type[Sequence[UserType]]:
class Result(UserList):
... # Cut out the implementation for brevity's sake
return Result
Сгенерированный «TypeSequence» делает что-то с проверками типов, чтобы генерировать только сериализуемые структуры данных, что не важно для этого вопроса. Дело в том, что Вы должны быть в состоянии сделать что-то вроде этого:
MyIntSequence = TypeSequence(int)
MyIntSequence((1, 2, 3)) -> [1, 2, 3] with type Sequence[Int]
MyTupleSequence = TypeSequence(tuple)
MyTupleSequence(((1, 2), (3, 4))) -> [(1, 2), (3, 4)] with type Sequence[tuple]
Мой вопрос : Правильно ли указаны аннотации типов?
Мои сомнения в основном связаны с ошибкой PyCharm для обеспечения типов, сгенерированных моей пользовательской функцией генератора. Может быть проблема с PyCharm, но я сомневаюсь в этом, так как он очень хорошо работает для стандартной библиотеки, которая в значительной степени использует одинаково сложные аннотации типов.
Простой пример, где вывод типа кажется неудачным:
Обратите внимание, как это отличается от этой версии списка:
У меня также много вопросов о том, что на самом деле делает TypeSequence. Я отредактировал эту реализацию, чтобы иметь более краткий пост, но здесь - полная реализация. Он выполняет принудительное приведение типов и проверку типов:
from collections import UserList
from typing import (Optional, Any, Sequence, Callable, Hashable, Dict, Mapping, Type, TypeVar,
)
UserType = TypeVar('UserType')
def TypeSequence(usertype: Type[UserType]) -> Type[Sequence[UserType]]:
class Result(UserList):
def __init__(self, *args):
from collections import Iterable
if len(args) == 0:
super(Result, self).__init__()
elif len(args) == 1:
if not isinstance(args[0], Iterable):
raise ValueError("Not a iterable")
if issubclass(usertype, tuple) and hasattr(usertype, "_fields"):
if any(not isinstance(x, Iterable) for x in args[0]):
raise ValueError("Invalid initializer for named tuple")
if len(args[0]) != len(usertype._fields):
raise ValueError(f"Not enough values to initialize {usertype}")
seq = (usertype(*x) for x in args[0])
else:
seq = (usertype(x) for x in args[0])
super(Result, self).__init__(seq)
Result.__name__ = f"TypeSequence[{usertype.__name__}]"
return Result
Не думаю, что это что-то добавляет к вопросу, но здесь вы go: D