《流畅的Python》5.8,5.9 获取关于参数的信息和函数注解 总结
1,理解param.kind含义:给形参传递参数的方式,是位置传递,还是关键字传递
2,框架可以使用bind方法在真正调用函数前验证参数;
框架和IDE等工具可以使用这些信息验证代码;
注解只是元数据,可以供IDE、框架和装饰器等工具使用。
3,执行下面语句可以得到一个signature对象,
import inspect sig = inspect.signature(func) sig.parameters属性 for name, param in sig.parameters.items(): pass sig.return_annotation属性 sig.bind(实参).arguments属性 for name, value in sig.bind(实参).arguments属性.items(): pass

1 def clip(text, max_len = 80): 2 end = None 3 if len(text) > max_len: 4 space_before = text.rfind(" ", 0, max_len) 5 if space_before >= 0 : 6 end = space_before 7 else: 8 space_after = text.rfind(" ", max_len) 9 10 if space_after >= 0: 11 end = space_after 12 13 if end is None: 14 end = len(text) 15 16 return text[:end].rstrip(" ") 17 18 19 20 # print(clip.__defaults__) 21 # print(clip.__kwdefaults__) 22 23 # a = clip.__code__.co_varnames 24 # print(a) 25 # print(type(a)) 26 # print(clip.__code__.co_argcount) 27 28 29 #和上面clip函数唯一的区别是参数中添加了/, * 30 def clip1(text, /,*,max_len = 80): 31 pass 32 33 34 35 #测试函数注解,即声明函数的类型,返回值的类型 36 def clip2(text : str, max_len:'int >0' = 80) -> str: 37 pass
1 from inspect import signature 2 from clip import clip, clip1, clip2 3 4 sig = signature(clip) 5 sig1 = signature(clip1) 6 print(sig) 7 print(str(sig)) 8 print("sig.parameters:\n",sig.parameters, '\n') 9 print('sig.parameters.items():\n',sig.parameters.items(), '\n') 10 print('sig.parameters.keys():\n',sig.parameters.keys(), '\n') 11 print('sig.parameters.values():\n',sig.parameters.values(), '\n') 12 13 for i in sig.parameters.values(): 14 print("parameter对象类型:",type(i)) #<class 'inspect.Parameter'> 15 print(" ") 16 17 18 #以下两种对比param.kind返回值 19 print("clip函数的param.kind值:") 20 for name, param in sig.parameters.items(): 21 print(param.kind, ':', name,"=", param.default ,',',param.annotation ) 22 23 24 print("\nclip1函数的param.kind值:") 25 26 for name1, param1 in sig1.parameters.items(): 27 print(param1.kind , ':', name ,"=", param1.default ) 28 29 print('\n查看各函数的参数的声明,即注解:') 30 print(clip.__annotations__) 31 print(clip1.__annotations__) 32 print(clip2.__annotations__) # {'text': <class 'str'>, 'max_len': 'int >0', 'return': <class 'str'>} 33 34 35 print("\n返回值的注解:") 36 sig2 = signature(clip2) 37 print(sig2.return_annotation) 38 39 40 print("\n对比两种 ") 41 for param in sig2.parameters.values(): 42 #示例使用的是note形式,学习这种方法 43 note = repr(param.annotation).ljust(13) 44 note1 = param.annotation 45 print(type(note1)) 46 print(note, ':', param.name, '=', param.default) 47 print(note1, ':', param.name, '=', param.default) 48 49 50
从运行结果可以看到,
clip函数中的text和max_len参数可以通过POSITIONAL_OR_KEYWORD传递实参;
而clip1函数中text只能通过POSITIONAL_ONLY传递实参,而max_len只能通过KEYWORD_ONLY传递实参;

下面例子还使用了bind方法,
#注意:传值给可变参数*content时,一定不要带上content=什么什么,如果带上content,则会被attrs捕获当成字典 def tag(name, *content, cls=None, **attrs): #注意:传值给可变参数*content时,一定不要带上content=什么什么,如果带上content,则会被attrs捕获当成字典 print('name:',name, ',','content:', content, ',','cls:', cls,',','attrs:', attrs) """生成一个或多个HTML标签""" if cls is not None: attrs['class'] = cls if attrs: attr_str = ' '.join('%s="%s"'%(attr, value) for attr, value in sorted(attrs.items())) else: attr_str = '' if content: return '\n'.join('<%s %s>%s</%s>'% (name, attr_str, c, name) for c in content) else: return '<%s %s />'%(name, attr_str) #为了查看param.kind所有值,添加了city参数 def tag1(name,/, city, *content, cls=None, **attrs): pass print(tag('br'), '\n') print(tag('p', 'hello'), '\n') print(tag('p', 'hello', 'world'), '\n') print(tag('p', 'hello', id=33), '\n') print(tag('p', 'hello', 'world', cls='sidebar'), '\n') print(tag(content='testing', name="img"), '\n') #即使名字和可变参数名*content相同,也会被attrs捕获 my_tag = {'name': 'img', 'title': 'Sunset Boulevard', 'src': 'sunset.jpg', 'cls': 'framed' } print(tag(**my_tag), '\n') print("下面测试 inspect模块:") import inspect sig = inspect.signature(tag) sig1 = inspect.signature(tag1) print(sig) print(sig.parameters) print('\ntag函数中各参数传递实参的方式:') for _, param in sig.parameters.items(): print(param.kind ) print('\ntag1函数中各参数传递实参的方式:') for _, param1 in sig.parameters.items(): print(param1.kind) my_tag2 = {'name': 'img', 'title': 'Sunset Boulevard', 'src': 'sunset.jpg', 'cls': 'framed' } #通过bind方法传递实参 bound_args = sig.bind(**my_tag2) print(bound_args) print(bound_args.arguments) # print(type(bound_args.arguments)) for name, value in bound_args.arguments.items(): print(name, '=', value)


浙公网安备 33010602011771号