2016-10-05 25 views
9

我使用新的Python 3.5模块typing,它一直很欢乐。打字模块 - 字符串文字类型

我想知道如何根据确切的字符串文字来指定一个类型。例如,一个函数保证返回四个字符串之一 - “北”,“西”,“东”,“南 - 我们如何表达作为特定类型变量,而不是仅仅str

我通过文件看,找到Union类型和TypeVar功能,但无法找到答案

表达这个问题的一个例子功能:

def compute_quadrant(x: int, y: int) -> str: 
    if x > 0 and y > 0: 
     return 'I' 
    elif x < 0 and y > 0: 
     return 'II' 
    elif x < 0 and y < 0: 
     return 'III' 
    elif x > 0 and y < 0: 
     return 'IV' 

而不是仅仅返回str,我喜欢返回一个更具体的类型,它是四个值之一 - "I","II","III""IV"

在Typescript中,可以这样做:type Quadrant = "I" | "II" | "III" | "IV" - 这个用例中有typing模块有什么好的Python糖吗?

+5

与打字无关,但你认为'enum'? –

+0

我可以问,你为什么需要这样的东西?因为类型注释是为查看代码的文本编辑器和程序员制作的。如果你可以限制函数可能返回的元素的范围,那么你绝对可以通过查看代码来说。 –

+0

也许这个特定的函数没有概述用例(因为它简单直接),但是在编写代码时,我想尽可能地为我的对等提供尽可能多的上下文。在处理数据和对对象执行复杂操作时,我希望能够提供非常严格和精确的类型。此外,分析工具能够根据类型找到优化点 - 例如永远不会被击中的代码路径或明显的错误。 – fructosewizard

回答

1

无视您询问的typing模块,您的问题的一种解决方案可能是使用Enum,正如多个注释中所设想的那样。代码如下:

from enum import Enum 

class Quadrant(Enum): 
    I = 1 
    II = 2 
    III = 3 
    IV = 4 

def compute_quadrant(x: int, y: int) -> Quadrant: 
    if x > 0 and y > 0: 
     return Quadrant.I 
    elif x < 0 and y > 0: 
     return Quadrant.II 
    elif x < 0 and y < 0: 
     return Quadrant.III 
    elif x > 0 and y < 0: 
     return Quadrant.IV 
    # return None # this is what happens without an else clause! 

if __name__ == "__main__": 
    quad = compute_quadrant(1, -1) 
    print(quad, type(quad))    # -> Quadrant.IV <enum 'Quadrant'> 
    print(quad.name, type(quad.name)) # -> IV <class 'str'> 
    print(quad.value, type(quad.value)) # -> 4 <class 'int'> 

正如你所看到的,你可以使用枚举名和值。该名称是您要求的字符串之一。

我在这里看到的一个问题是函数中的missing else子句和mypy当前接受None作为Quadrant的有效返回值的行为。这应该手动处理。