Переменная/аргумент подсказки типа, который сам по себе является типом, но должен допускать объединения.Python

Программы на Python
Ответить
Anonymous
 Переменная/аргумент подсказки типа, который сам по себе является типом, но должен допускать объединения.

Сообщение Anonymous »

Я пытаюсь создать класс дескриптора и хочу предоставить пользователям аккуратные подсказки по типам. Идея примерно такая:

Код: Выделить всё

class MyModule(Module):
a = Connector(float)
b = Connector(Union[float, str, int])
c = Connector(str)

@c.callback
def get_c(self):
return f'This is a string with {self.a} and {self.b}'
а пользователями будут люди, разрабатывающие подклассы модуля. С он работает довольно хорошо, но я сталкиваюсь с трудностями при получении правильных типов для объектов Union. Я сделал следующий простой пример, который в настоящее время подходит для mypy:

Код: Выделить всё

from typing import TypeVar, Generic, overload, Any, reveal_type, Callable, Union, Dict, Self, Optional

T = TypeVar('T')

class Module:
__data__: Dict[str, Any]

def __init__(self):
self.__data__ = {}

class Connector(Generic[T]):
_type: type[T]
_name: str

@overload
def __get__(self, instance: None, owner: type[Module]) -> 'Connector[T]': ...

@overload
def __get__(self, instance: Module, owner: type[Module]) -> T: ...

def __get__(self, instance: Union[None, Module], owner: type[Module]) -> Union[T, 'Connector[T]']:
if instance is None:
return self

return instance.__data__[self._name]

def __set__(self, instance: 'Module', value: T) -> None:
instance.__data__[self._name] = value

@overload
def __init__(self, _type: type[T]) -> None: ...

@overload
def __init__(self, _type: Any) -> None: ...

def __init__(self, _type: type[T] | Any):
self._type = _type

def __call__(self, value: T) -> T:
return value

def __set_name__(self, name, owner: type['Module']) -> None:
self._name = name

class MyModule(Module):
x = Connector(float)
y = Connector[float|str](Union[float, str])
z = Connector(float|str)  # type: ignore

reveal_type(MyModule.x)  # revealed type is Connector[float]
reveal_type(MyModule.y)  # revealed type is Connector[float|str]
reveal_type(MyModule.z)  # revealed type is Connector[Any]

m = MyModule()
reveal_type(m.x)  # revealed type is float
reveal_type(m.y)  # revealed type is float|str
reveal_type(m.z)  # revealed type is Any
Можно использовать подход для MyModule.y, но для этого потребуется дублировать Union. Мне также нужен тип во время выполнения, поэтому я не могу только заполнить параметры. Но, очевидно, было бы неплохо, если бы правильный тип Union был указан и для m.z.
Есть идеи? Текущий выбор для Type[T] | Любой, который я позаимствовал у TypeAdapter от pydantic. Я видел это: Как мне ввести подсказку для переменной, значение которой само по себе является подсказкой типа? но заменив Type[T] | Любой с более длинным объединением дает мне тот же результат, что и mypy. Кроме того, похоже, этот вариант не специализируется на использовании T.

Подробнее здесь: https://stackoverflow.com/questions/798 ... low-unions
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»