Python学习笔记——类型注解基础知识

文章探讨了Python的动态类型如何简化编程,但可能导致代码可读性降低。通过函数文档和类型注解,如Sphinx和Python3.5后的类型注解功能,作者强调了提高代码清晰度的重要性,并介绍了如何使用typing模块进行类型标注以增强代码可维护性。
摘要由CSDN通过智能技术生成

Python是动态类型语言,使用变量时不需要做任何类型声明,这是Python相比其它语言的一个重要优势:它减少了我们的心智负担,让写代码变得更容易。尤其对于我们很多新手来说,“不用声明类型”无疑会让学Python这件事变得简单很多。

但任何事务都有其两面性。动态类型所带来的缺点是代码的可读性会因此大打折扣。

读读下面这段代码:

def remove_invalid(items):
    """剔除items里面的无效的元素"""
    ...

对于使用者来说,函数接收的items参数是什么类型?是一个装满数字的列表,还是一个装满字符串的集合?还是一个用户字典?对于调用者,根本无从得知。甚至对于编写者,过很长时间后,也可能会搞不懂了。

为了解决动态类型的可读性问题,最常见的办法是在函数文档(docstring)里做文章,把每个函数参数的类型与说明全部都写到函数文档里。

下面是增加了Python官方推荐的Sphinx格式文档后的代码:

def remove_invalid(items):
    """剔除items里面的无效的元素"""

    :param items:待剔除对象
    :type items:包含整数的列表,[int,...]
    ...

上面代码中,在函数文档里,用:type items 注明了items是一个整数列表。调用人员读到就清楚了参数的类型。

标注类型的方法不止于这一种,在Python3.5版本以后,可以使用类型注解功能直接注明变量类型。只需要在变量后添加类型,并用冒号隔开即可,比如func(value: str),表示函数func的参数value是字符串类型。

使用类型注解后的上面代码如下:

from typing import List

def remove_invalid(items: List[int]):
    """剔除items里面的无效的元素"""
    ...

List表示参数为列表类型,[int]表示里面的成员是整形。

typing是类型注解用到的主要模块,除了List以外,该模块内还有许多与类型有关的特殊对象,举例如下:

  • Dict:字典类型,例如Dict[str,int]代表键为字符串,值为整形的字典。
  • Callable:可调用对象,例如Callable[[str,str],List[str]]表示接收两个字符串作为参数,返回字符串列表的可调用对象。
  • TextIO:使用文本协议的类文件类型,相应地,还有二进制类型BinaryIO.
  • Any:代表任何类型
  • 说明:“类型注解”只是一种有关类型的注释,不提供任何校验功能。要校验类型正确性,需要使用其他类型检查工具(如mypy等)。

不仅可以给变量加上类型注解,还可以给函数的返回值加上类型注解,如下代码做了演示:

1)下面代码没有任何类型注解:

class Duck:
    """鸭子类

    :param color: 鸭子颜色
    """

    def __init__(self,color):
        self.color = color

    def quack(self):
        print(f"嗨,这是一只{self.color}的鸭子"}

    def create_random_ducks(number):
        """创建一批随机颜色的鸭子

        :param number: 需要创建的鸭子数量
        """
        ducks = []
        while number > 0:
            color = random.choice(['yellow','white','gray'])
            ducks.append(Duck(color=color))
            number -= 1
        return ducks

2)下面是添加了类型注解代码:

from typing import List  
import random  
  
class Duck:  
   
    def __init__(self, color: str):   # 参数color类型为字符串  
        self.color = color  
   
    def quack(self) -> None:         # 函数返回值类型为None  
        print(f"嗨,这是一只{self.color}的鸭子")  

   
def create_random_ducks(number: int) ->List[Duck]: # 参数number类型为整形  
    ducks: List[Duck] = []          # 变量ducks是一个列表,列表元素是Duck类型  
    while number > 0:  
        color = random.choice(['yellow', 'white', 'gray'])  # 这里对color变量进行类型注解  
        ducks.append(Duck(color=color))  
        number -= 1  
    return ducks

ducks = create_random_ducks(5)

for duck in ducks:
    duck.quack()
  • 从上面代码可以看出,通过-> 给函数返回值添加类型注解
  • 可以用typing模块的特殊对象List来标注列表成员的具体类型,注意,这里用的是[],不是()
  • 声明变量时候,可以为其加上类型注解,但类型注解是可选的,非常自由,比如上面代码中如下这行的color变量就没有注解。

color = random.choice(['yellow','white','gray'])

如果加上注解是这样子的:

color: str = random.choice(['yellow','white','gray'])

可以把Python里的类型注解当成一种用于提升代码可读性的特殊注释,因为它就像注释一样,只提升代码的说明性,不会对程序的执行过程产生任何实际影响,Python并不会做校验。

至于函数文档好,还是类型注解好,仁者见仁智者见智。我学习这块内容的理解是,函数文档还是要有的,给调用者(包括自己)更好地阅读,尤其使用Pycharm这类工具调用,会有很好的提示,这一点特别好。在编写函数时,对参数及返回值做注解也很有意义,不仅提升代码的可读性,可以让自己写函数体内的具体逻辑代码更清晰,或者做必要的验证,增强代码的健壮性。

本文主要摘自朱雷老师《Python工匠》书中内容,修改了代码部分内容。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值