Python函数:函数注解与类型提示的写法与实践

发布时间:2026/7/25 16:18:19
Python函数:函数注解与类型提示的写法与实践 Python函数函数注解与类型提示的写法与实践一、开篇让代码声明意图Python是动态类型语言——你不需要声明变量的类型。这在快速开发时很方便但在大型项目中缺乏类型信息常常导致难以发现的bug。⌨️ 从Python 3.5开始函数注解Function Annotations和类型提示Type Hints成为了标准# 没有类型提示的函数defcalculate_total(items,discount,tax_rate):这些参数应该传什么类型返回值是什么类型pass# ✅ 有类型提示的函数——意图清晰defcalculate_total(items:list[dict],# 应该是字典列表discount:float,# 折扣率小数tax_rate:float0.13# 税率默认13%)-float:# 返回浮点数现在一看就知道该怎么传参了pass 类型提示不会影响运行时行为——Python不会因为类型不匹配而报错。它们的主要作用是提升代码可读性、获得更好的IDE支持自动补全、错误提示、以及配合静态类型检查工具如mypy在运行前发现问题。二、基本类型注解2.1 内置类型的注解# 基本类型defgreet(name:str)-str:returnfHello,{name}!defadd(a:int,b:int)-int:returnabdefis_adult(age:int)-bool:returnage18defcalculate_average(scores:list[float])-float:Python 3.9可以用list[float]returnsum(scores)/len(scores)ifscoreselse0.0# 复杂参数defprocess_data(data:list[int],# 列表Python 3.9写法config:dict[str,str],# 字典Python 3.9写法factor:float1.0,)-list[float]:# 返回浮点数列表return[d*factorfordindata]# 使用resultprocess_data([1,2,3],{mode:fast},2.0)print(result)# [2.0, 4.0, 6.0]2.2 typing模块的常用类型fromtypingimport(List,Dict,Tuple,Set,Optional,Union,Any,Callable,Sequence,Mapping,Iterable,Iterator)# Python 3.8及以下用typing模块的版本defprocess_old(data:List[int],# 等价于 Python 3.9 的 list[int]config:Dict[str,str],# 等价于 Python 3.9 的 dict[str, str]sizes:Tuple[int,int],# 等价于 Python 3.9 的 tuple[int, int]tags:Set[str],# 等价于 Python 3.9 的 set[str])-List[float]:pass# Optional —— 可以是某类型或Nonedefget_user(user_id:int)-Optional[dict]:返回用户字典或Noneusers{1:{name:张三}}returnusers.get(user_id)userget_user(1)print(user)# {name: 张三}user2get_user(99)print(user2)# None# Union —— 可以是多种类型之一defparse_value(value:str)-Union[int,float,str]:尝试解析值返回不同可能的类型try:returnint(value)exceptValueError:try:returnfloat(value)exceptValueError:returnvalueprint(parse_value(42))# 42 (int)print(parse_value(3.14))# 3.14 (float)print(parse_value(hello))# hello (str)# Any —— 任意类型defdebug_print(obj:Any)-None:接受任何类型的参数print(fDEBUG:{obj!r})# Callable —— 函数类型defapply_transform(data:list[int],transform:Callable[[int],int]# 接收int返回int的函数)-list[int]:return[transform(x)forxindata]resultapply_transform([1,2,3],lambdax:x*2)print(result)# [2, 4, 6]三、高级类型注解3.1 类型别名和自定义类型fromtypingimportTypeAlias# 类型别名UserId:TypeAliasintUserName:TypeAliasstrJsonDict:TypeAliasdict[str,any]defget_user_name(user_id:UserId)-UserName:returnf用户{user_id}# 复杂的嵌套类型Matrixlist[list[float]]# 矩阵defmatrix_multiply(a:Matrix,b:Matrix)-Matrix:矩阵乘法pass# 使用Literal限制取值fromtypingimportLiteraldefset_log_level(level:Literal[DEBUG,INFO,WARNING,ERROR])-None:level只能是这四个值之一print(f日志级别设置为:{level})set_log_level(INFO)# ✅# set_log_level(TRACE) # mypy会报警告运行时不会报错# 使用TypedDict定义字典结构fromtypingimportTypedDictclassUserDict(TypedDict):定义用户字典的结构name:strage:intemail:stractive:booldefcreate_user(data:UserDict)-str:returnf用户{data[name]}已创建# Final —— 常量不应被修改fromtypingimportFinal MAX_RETRIES:Final3API_BASE_URL:Finalhttps://api.example.com3.2 类型注解在类中的应用fromtypingimportClassVar,SelfclassBankAccount:# ClassVar —— 类变量所有实例共享bank_name:ClassVar[str]第一银行total_accounts:ClassVar[int]0def__init__(self,owner:str,balance:float0.0)-None:self.owner:strowner# 实例属性self.balance:floatbalance BankAccount.total_accounts1defdeposit(self,amount:float)-float:存款——返回新的余额self.balanceamountreturnself.balancedeftransfer_to(self,other:Self,amount:float)-bool:转账到另一个账户——Self表示同类型的实例ifself.balanceamount:self.balance-amount other.balanceamountreturnTruereturnFalse# 使用acc1BankAccount(张三,1000.0)acc2BankAccount(李四,500.0)acc1.transfer_to(acc2,300.0)print(f张三:{acc1.balance}, 李四:{acc2.balance})# 张三: 700.0, 李四: 800.0四、类型检查工具4.1 查看注解信息defprocess(data:list[int],factor:float1.5)-dict[str,float]:处理数据resultsum(data)*factorreturn{total:result,count:len(data)}# __annotations__属性存储了类型注解print(process.__annotations__)# {data: list[int], factor: class float, return: dict[str, float]}# 类型注解只是元数据——不影响运行时print(process([1,2,3],2.0))# {total: 12.0, count: 3}print(process([a,b],hello))# 运行时不报错但类型不对# mypy会在静态检查时报错4.2 mypy使用简介# 安装mypy$ pipinstallmypy# 检查Python文件$ mypy script.py# 输出示例# script.py:10: error: Argument 1 to process has incompatible type list[str];# expected list[int]# mypy通过类型注解和代码逻辑推断类型错误# 它不运行你的代码而是静态分析# 即使你的代码运行正常mypy也能发现潜在问题defget_config(key:str)-Optional[dict]:config{debug:{enabled:True}}returnconfig.get(key)configget_config(debug)# config可能是None——使用前需要检查# config[enabled] # mypy警告: Item None of Optional[dict] has no attribute __getitem__# ✅ 正确处理Optionalconfigget_config(debug)ifconfigisnotNone:print(config[enabled])# mypy放心了——你检查过了五、总结类型提示是现代Python的重要特性。它让你在享受动态类型灵活性的同时获得静态类型的代码辅助和质量保证。核心要点类型注解不影响运行时——它们是元数据供工具使用Python 3.9用list[int]旧版本用typing.List[int]IDE支持——代码补全、错误提示、重构辅助mypy——在CI中加mypy检查防止类型错误上线✅渐进式采用策略不用一次性给所有代码加类型。从公共API开始逐步扩展。Any和Optional是你的过渡工具。