背景
最近学习Python,今天用python练习leetcode时,看到默认生成的函数定义
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
其中"->"语法没见过,包括书上都极少讲,就深入看下,查阅pythondoc,原来是python的语法特性:annotation,标注。
标注的定义
关联到某个变量、类属性、函数形参或返回值的标签,被约定作为 类型注解 来使用。局部变量的标注在运行时不可访问,但全局变量、类属性和函数的标注会分别存放模块、类和函数的 _annotations_ 特殊属性中。
注意:标注仅对__annotations__属性有影响,是一种类似注释的特性,去除标注代码,对函数的实际运行不会有任何影响
主要文档:
variable annotation,变量标注
function annotation,函数标注
最佳实践
变量标注
在jupyter中代码,python 3.9.12
class CMyObj:
m_num:int = 0
obj = CMyObj()
obj
obj.__annotations__
type(obj.__annotations__)
运行结果
<__main__.CMyObj at 0x23b494f54f0>
{'m_num': int}
dict
可以看到属性__annotations__以及其本质是个dict的字典类型
以上如果直接读取 m_num.__annotations__属性会失败,即变量标注仅保存在对象类型的属性中
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [19], in <cell line: 6>()
4 obj
5 obj.__annotations__
----> 6 obj.m_num.__annotations__
AttributeError: 'int' object has no attribute '__annotations__'
函数标注
回顾函数的定义(来自pythondoc 函数定义)
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
举例
def func(v1: str, v2: str = None) -> str:
return '111'
func
func.__annotations__
type(func.__annotations__)
其中 ‘: str’ ‘-> str’都属于标注,前者是参数,后者是返回值。其目的就是让调用者知道,这个参数应该传入哪种类型的变量,返回哪种类型的结果。
运行结果:
<function __main__.func(v1: str, v2: str = None) -> str>
{'v1': str, 'v2': str, 'return': str}
'111'
标注最佳实践
python文档
- 应避免直接给对象的
__annotations__
成员赋值。请让 Python 来管理__annotations__
。 - 如果直接给某对象的
__annotations__
成员赋值,应该确保设成一个dict
对象。 - 如果直接访问某个对象的
__annotations__
成员,在解析其值之前,应先确认其为字典类型。 - 应避免修改
__annotations__
字典。 - 应避免删除对象的
__annotations__
属性。
个人观点
标注是个只读属性,主要用于注释,运行时可以打印日志等辅助调试,或追溯信息,但是不要把它运用于业务逻辑。