簡體   English   中英

Python Typing:根據函數參數聲明返回值類型

[英]Python Typing: declare return value type based on function argument

假設我有將類型作為參數並返回該類型實例的函數:

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)

您正在尋找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對象都接受參數,但您可以將其限制為一些與您的示例類似的變量。

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 (來自typingtyping typing_extensions )。


請注意,如果明確只想將42傳遞給Callable ,則可以使用Literal (來自typingtyping_extensions )來指定這一點。

R = TypeVar('R')


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

請注意,任何Callable[[int], R]類型的函數也滿足Callable[[Literal[42]], R]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM