Python Набор: объявить тип возвращаемого значения на основе аргумента функции - PullRequest
3 голосов
/ 13 февраля 2020

Предположим, у меня есть функция, которая принимает тип в качестве аргумента и возвращает экземпляр этого типа:

def fun(t):
    return t(42)

Затем я могу вызвать его и получить объекты предоставленных типов:

fun(int)           # 42
fun(float)         # 42.0
fun(complex)       # (42+0j)
fun(str)           # "42"
fun(MyCustomType)  # something

Этот список не является исчерпывающим, я хотел бы иметь возможность использовать любой тип с соответствующим конструктором.

Затем я хотел бы добавить подсказки типов для этой функции. Какой должна быть подсказка типа для возвращаемого значения этой функции?


Я пытался , используя просто t, поскольку t это тип:

def fun(t: type) -> t:
    return t(42)

, но это не работает:

main.py: 1: ошибка: имя 't' не определено


Этот ответ предлагает с использованием TypeVar:

from typing import TypeVar

T = TypeVar("T")

def fun(t: T) -> T:
    return t(42)

Но это не так, поскольку T обозначает тип, поэтому предполагает, что возвращается сам тип, а не его экземпляр. Mypy отвергает это:

main.py: 6: ошибка: «объект» не вызывается


Использование Any очевидно работает , но я чувствую, что это слишком расплывчато, это не передает намерения:

from typing import Any

def fun(t: type) -> Any:
    return t(42)

Ответы [ 2 ]

3 голосов
/ 13 февраля 2020

Вы ищете typing.Type, поэтому что-то вроде:

from typing import TypeVar, Type

T = TypeVar("T", str, complex, float, int)

def fun(t: Type[T]) -> T:
    return t(42)

fun(int)
fun(float)
fun(complex)
fun(str)

Обратите внимание, что переменная вашего типа должна быть ограничена, поскольку не все Type объекты принимают аргументы, но вы можете ограничьте это несколькими, которые нравятся вашему примеру.

2 голосов
/ 13 февраля 2020

TLDR: вам нужно TypeVar для возвращаемого типа вызова t:

def fun(t: Callable[[int], R]) -> R:
    ...

Ограничение на тип здесь слишком ограничено. Функция принимает любые Callable, которые принимают целое число, и тип возвращаемого значения функции - Callable. Это можно указать, используя TypeVar для возвращаемого типа:

from typing import Callable, TypeVar


R = TypeVar('R')  # the variable return type


def fun(t: Callable[[int], R]) -> R:
    return t(42)

fun(int)                            # Revealed type is 'builtins.int*'
fun(float)                          # Revealed type is 'builtins.float*'
reveal_type(fun(lambda x: str(x)))  # Revealed type is 'builtins.str*'

Это также работает для типов, потому что создание экземпляра типа является вызовом.

Если более сложная подпись, например с ключевыми словами, необходимо, используйте Protocol (из typing или typing_extensions).


Обратите внимание, что если один явно хочет передать только 42 Callable, Literal (от typing или typing_extensions) могут использоваться для указания этого.

R = TypeVar('R')


def fun(t: Callable[[Literal[42]], R]) -> R:
    return t(42)

Обратите внимание, что любая функция типа Callable[[int], R] также удовлетворяет Callable[[Literal[42]], R].

...