python的注解是通过装饰器模式实现的,@注解本质是一个函数
def my_annotation(**kwds):
def decorate(fn):
for item in kwds.items():
print(item)
return fn
return decorate
@my_annotation(value="this is a annotation", author="Jack")
def test_annotation():
print("test...")
if __name__ == "__main__":
annos = test_annotation.__annotations__
print(annos)
打印结果:
('value', 'this is a annotation')
('author', 'Jack')
{}
上述结果可以理解为将注解信息 { value="this is a annotation", author="Jack" } 作为参数传到my_annotation函数中,将test_annotation函数作为参数传到装饰器函数decorate中
注意decorate这里返回的是fn函数本身,因为你返回什么,加了注解的test_annotation就会变成什么,返回str,则test_annotation将不再是函数,而是str,因此test_annotation.__annotations__会报错不存在该属性,所以要返回fn本身,保持函数类型不变
打印信息最后test_annotation的注解为空字典 {},说明直接在方法上加@注解,其信息不会注入进去,因此需要手动set
def my_annotation(**kwds):
def decorate(fn):
for item in kwds.items():
#print(item)
key = item[0]
value = item[1]
fn.__annotations__[key] = value
return fn
return decorate
@my_annotation(value="this is a annotation", author="Jack")
def test_annotation():
print("test...")
if __name__ == "__main__":
annos = test_annotation.__annotations__
print(annos)
打印结果:
{'value': 'this is a annotation', 'author': 'Jack'}
这样注解信息就被注入到方法中了。由于__annotations__本质是一个字典,因此可以采用字典的那套方法去判断、获取方法上的注解信息
一般写一个基于反射的python框架中很可能会需要动态获取注解信息,下面给出一个简单获取案例
def codeC():
print("codes written by someone")
@my_annotation(author="Guido van Rossum")
def codeA():
print("codes written by Guido van Rossum")
@my_annotation(author="虚拟WORLD-er")
def codeB():
print("codes written by 虚拟WORLD-er")
# 分析程序是否被采用
def check_code(codes):
author = codes.__annotations__.get("author")
if author == None:
print("代码未认证!")
elif author == "Guido van Rossum":
print("{}: 大佬代码!采用!".format(author))
elif author == "虚拟WORLD-er":
print("{}: 菜鸡代码!弃用!".format(author))
else:
print("待定...")
if __name__ == "__main__":
check_code(codeC)
check_code(codeA)
check_code(codeB)
打印结果:
# 代码未认证!
# Guido van Rossum: 大佬代码!采用!
# 虚拟WORLD-er: 菜鸡代码!弃用!
python注解进阶可见:该文