《流畅的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)

 

 

posted @ 2023-09-20 19:26  limalove  阅读(24)  评论(0)    收藏  举报