使用函数的返回类型指定类型提示

时间:2019-09-12 10:12:19

标签: python python-3.x typing python-typing

我想暗示变量的类型作为特定函数的返回类型(无需手动指定函数的返回类型)。

我无法以可以用作其他变量提示的方式从函数中提取返回值类型。

def dostuff() -> T:
    StuffContainer = namedtuple("StuffContainer", ["x", "y"])
    return StuffContainer(1, 2)

def getX(a : T):
    return a.x

相当于我想做的事的C ++:

auto dostuff() {
    struct data {
        int x;
        int y;
    };
    return data {1, 2};
}

int getX(decltype(dostuff()) a) {
    return a.x;
}

2 个答案:

答案 0 :(得分:2)

在PEP 484打字生态系统中没有与decltype等效的文件。更广泛地说,实际上没有一种很好的方式来表达“匿名”类型。

因此,您键入代码的规范方法是执行以下操作:

StuffContainer = namedtuple("StuffContainer", ["x", "y"])

def dostuff() -> StuffContainer:
    return StuffContainer(1, 2)

def getX(a: StuffContainer):
    return a.x

如果您担心返回的类型太长且不方便写出来,则可以使用type aliases将其缩短一点:

StuffContainer = namedtuple("StuffContainer", ["x", "y"])

# S is now an alias of StuffContainer. The two types can be
# used interchangeably.
S = StuffContainer

def dostuff() -> S:
    return StuffContainer(1, 2)

def getX(a: S):
    return a.x

如果担心的是您不想对dostuff进行编码,则返回特定的 一个namedtuple,而您只想返回一个带有'x'和' y'属性,您也许可以使用协议-您可以在in the PEPmypy docs中找到有关协议的更多信息。 (不幸的是,尽管在正式的Python输入模块文档中还没有关于它们的任何信息。)

例如:

from typing import NamedTuple

# If you're using Python 3.8+, you can do:
from typing import Protocol

# If you want to support older versions of Python,
# run 'pip install typing_extensions' and do the below instead
from typing_extensions import Protocol

# Any type that has 'x' and 'y' attributes is compatible with this.
class HasXAndY(Protocol):
    # Making these properties to declare that they're read-only,
    # for maximum flexibility.
    @property
    def x(self) -> int: ...
    @property
    def y(self) -> int: ...


def dostuff() -> HasXAndY:
    # Note: I'm switching to a version of namedtuple that lets me associate
    # types with each field, mostly just for demonstration purposes. At runtime,
    # it behaves identically to collections.namedtuple.
    StuffContainer = NamedTuple("StuffContainer", [("x", int), ("y", int)])
    return StuffContainer(1, 2)

def get_x(obj: HasXAndY) -> int:
    return obj.x

# Type-checks
get_x(dostuff())


class Unrelated:
    def __init__(self, x: int, y: int, z: int) -> None:
        self.x = x
        self.y = y
        self.z = z

# Also type-checks
get_x(Unrelated(1, 2, 3))

答案 1 :(得分:0)

我不确定我是否真的喜欢这个,但是你可以做到。
方法的类型提示存储在注释中,因此您可以动态编辑它们。

In [25]: class T: 
    ...:     x: int 
    ...:     y: str 
    ...:                                                                                                                                                                     

In [26]: def dostuff() -> T: 
    ...:     pass 
    ...:                                                                                                                                                                     

In [27]: def getX(a: T): 
    ...:     pass 
    ...:                                                                                                                                                                     

In [28]: getX                                                                                                                                                                
Out[28]: <function __main__.getX(a: __main__.T)>

In [29]: getX.__annotations__['return']=T.__annotations__['x']                                                                                                               

In [30]: getX                                                                                                                                                                
Out[30]: <function __main__.getX(a: __main__.T) -> int>

我真的不认为这是您的意思,但是也许。