介绍

python不需要和其他编程语言那样,定义变量的时候直接指定int、float之类的类型,代码确实简洁了很多,但是代码量大起来之后,就会变的特别的繁杂,所以python提供的类型提示功能也就异常重要了。

  • 类型提示是Python3.6+版本加入的功能;
  • 类型提示就是在定义变量的时候给变量指定一个类型,比如定义一个str类型的变量;
  • 类型提示在工程项目中很重要,配合静态检查、减少bug、方便开发;
  • 类型提示使用简洁…

简单使用

  • 编写一个简单的无提示的例子
def get_full_name(first_name, last_name):
    full_name = first_name.title() + " " + last_name.title()
    return full_name

print(get_full_name("john", "doe"))

.title()是 Python 字符串方法之一,可以将字符串中每个单词的首字母都变成大写,并返回新的字符串。具体而言,该方法会将每个单词的第一个字母转换为大写,然后将其余字母都转换为小写。
可以在编写 Python 代码时使用这个方法来确保字符串每个单词的格式都是首字母大写的。例如,如果一个人的名字只有小写字母,则可以使用 .title() 方法将其转换为首字母大写的格式。
运行输出:

John Doe
  • 添加类型提示,将下面代码中的参数从:
first_name, last_name

改到:

first_name: str, last_name: str

完整代码:

def get_full_name(first_name: str, last_name: str):
    full_name = first_name.title() + " " + last_name.title()
    return full_name

print(get_full_name("john", "doe"))
  • 使用方法总结:

    • 在变量或形参后面加上,后面接类型就行,例如int 、float,就好了;

    • 返回值的类型提示就是在函数后面用箭头->指定;

      如:

    def get_full_name(first_name: str, last_name: str) -> str:
        full_name = first_name.title() + " " + last_name.title()
        return full_name
    

可以做什么

  • 在IDE中写代码的时候,没有类型提示的时候,需要调用一个"将第一个字母转换为大写形式的方法"。输入函数的第一个参数 first_name,这个时候代码补全功能是起不了作用的;当给参数类型后,就能有完美的类型提示了;
  • 其次就是知道了类型,在写代码的时候,就能很简明的发现其中的错误;
  • 如上,声明类型提示的主要场景就是用于函数的参数,也是FastAPI中使用的主要场景。

简单类型

  • int
  • float
  • bool
  • bytes:代表字节串,是一个类型。字符串(str)由多个字符组成,以字符为单位进行操作;字节串(bytes)由多个字节组成,以字节为单位进行操作,由于 bytes 保存的就是原始的字节(二进制格式)数据,因此 bytes 对象可用于在网络上传输数据,也可用于存储各种二进制格式的文件,比如图片、音乐等文件。
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
    return item_a, item_b, item_c, item_d, item_d, item_e

嵌套类型

列表

from typing import List

def process_items(items: List[str]):
    for item in items:
        print(item)

:声明变量

输入List作为类型

表示变量items是一个list,并且这个列表里每个元素都是str

元组和集合

元组(tuple)与列表类似,不同之处在于元组的元素不能修改。元组写在小括号(())里,元素之间用逗号隔开,元组中的元素类型可以不相同;

tuple = ( 'abcd', 786 , 2.23, 'runoob', 70.2 )
tinytuple = (123, 'runoob') print (tuple) # 输出完整元组
print (tuple[0]) # 输出元组的第一个元素 
print (tuple[1:3]) # 输出从第二个元素开始到第三个元素 
print (tuple[2:]) # 输出从第三个元素开始的所有元素 
print (tinytuple * 2) # 输出两次元组 
print (tuple + tinytuple) # 连接元组

集合(set)类似于数学中的集合:是一组key值,不包含重复元素,同时也是可变的、无序的、有限的集合,其元素是唯一的、不可变的。没有(不支持)索引和切片操作。

from typing import Set, Tuple

def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
    return items_t, items_s

上面这段代码表示:

变量items_t是一个tuple,其中前两个元素是int类型,最后一个元素是str类型;

变量items_s是一个set,其中的每个元素都是bytes类型。

字典

from typing import Dict

def process_items(prices: Dict[str, float]):
    for item_name, item_price in prices.items():
        print(item_name)
        print(item_price)

定义dict的时候,需要传入两个类型,分别声明键和值的类型;

上面代码表示:

变量prices是一个dict,这个dict的所有键都是str类型,所有的值都是float类型。

class Person:
    def __init__(self, name: str):
        self.name = name

def get_person_name(one_person: Person):
    return one_person.name

上面代码就表示one_person是一个Person类型的参数。

typing.Union

联合类型; Union[X, Y] 意味着:要不是 X,要不是 Y。

使用形如 Union[int, str] 的形式来定义一个联合类型。细节如下:

  • 参数必须是类型,而且必须至少有一个参数。

  • 联合类型的联合类型会被展开打平,比如:

    Union[Union[int, str], float] == Union[int, str, float]
    
  • 仅有一个参数的联合类型会坍缩成参数自身,比如:

    Union[int] == int  # The constructor actually returns int
    
  • 多余的参数会被跳过,比如:

    Union[int, str, int] == Union[int, str]
    
  • 在比较联合类型的时候,参数顺序会被忽略,比如:

    Union[int, str] == Union[str, int]
    
  • 你不能继承或者实例化一个联合类型。

  • 你不能写成 Union[X][Y]

  • 你可以使用 Optional[X] 作为 Union[X, None] 的缩写。

typing.Optional

可选类型。

Optional[X] 等价于 Union[X, None]

请注意,这与可选参数并非相同的概念。可选参数是一个具有默认值的参数。可选参数的类型注解并不因为它是可选的就需要 Optional 限定符。例如:

def foo(arg: int = 0) -> None:
    ...

另一方面,如果允许显式地传递值 None , 使用 Optional 也是正当的,无论该参数是否是可选的。例如:

def foo(arg: Optional[int] = None) -> None:
    ...

例:

def foo_v1(a: int, b:int = None):
    if b:
        print(a + b)
    else:
        print("parameter b is a NoneType!")

def foo_v2(a: int, b: Optional[int] = None):
    if b:
        print(a + b)
    else:
        print("parameter b is a NoneType!")

def foo_v3(a: int, b: Union[int, None] = None):
    if b:
        print(a + b)
    else:
        print("parameter b is a NoneType!")

#只传入a位置的实参
foo_v1(2)
foo_v2(2)
foo_v3(2)

# 输出
>>> parameter b is a NoneType!
>>> parameter b is a NoneType!
>>> parameter b is a NoneType!

加不加Optional这个其实没什么区别,python会默认最后一个赋值的形式参数为可选参数,加上Optional这个参数主要是为了增加可读性,毕竟形如“int = None”的形式参数赋值容易引起歧义,也即类型注释已经为整数类型,但是你传入的参数确实None(也即‘NoneType’类型),而添加Optional之后就相当于在int和None之间连接起来,也即默认是None,但是可以传入int类型的值(当然由于python没有强制,虽然注释为int类型,你还是可以传入其他类型)。