use inspect module to figure out the attributes in a function object.
there is a clip function below:
def clip(text, max_len=80):
""" return text clipped at the last space before or after max_len
"""
end = None
if len(text) > max_len:
space_before = text.rfind(' ', 0, max_len)
if space_before >= 0:
end = space_before
else:
space_after = text.rfind(' ', max_len)
if space_after >= 0:
end = space_after
if end is None:
end = len(text)
return text[:end].rstrip()
clip.__defaults__ # return a tuple which contains the default value
(80,)
clip.__code__
<code object clip at 0x0000000003DA89C0, file "<ipython-input-1-90da76271be0>", line 1>
dir(clip.__code__)
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'co_argcount',
'co_cellvars',
'co_code',
'co_consts',
'co_filename',
'co_firstlineno',
'co_flags',
'co_freevars',
'co_kwonlyargcount',
'co_lnotab',
'co_name',
'co_names',
'co_nlocals',
'co_stacksize',
'co_varnames']
clip.__code__.co_argcount # number of arguments
2
clip.__code__.co_varnames # name of variables
('text', 'max_len', 'end', 'space_before', 'space_after')
clip.__code__.co_freevars
()
clip.__code__.co_kwonlyargcount
0
clip.__code__.co_code
b'd\x01\x00}\x02\x00t\x00\x00|\x00\x00\x83\x01\x00|\x01\x00k\x04\x00rl\x00|\x00\x00j\x01\x00d\x02\x00d\x03\x00|\x01\x00\x83\x03\x00}\x03\x00|\x03\x00d\x03\x00k\x05\x00rB\x00|\x03\x00}\x02\x00ql\x00|\x00\x00j\x01\x00d\x02\x00|\x01\x00\x83\x02\x00}\x04\x00|\x04\x00d\x03\x00k\x05\x00rl\x00|\x04\x00}\x02\x00ql\x00n\x00\x00|\x02\x00d\x01\x00k\x08\x00r\x87\x00t\x00\x00|\x00\x00\x83\x01\x00}\x02\x00n\x00\x00|\x00\x00d\x01\x00|\x02\x00\x85\x02\x00\x19j\x02\x00\x83\x00\x00S'
import inspect
sig = inspect.signature(clip)
sig
<inspect.Signature at 0x4748710>
str(sig)
'(text, max_len=80)'
for name,param in sig.parameters.items():
print("{}:{} = {}".format(name,param.kind,param.default))
text:POSITIONAL_OR_KEYWORD = <class 'inspect._empty'>
max_len:POSITIONAL_OR_KEYWORD = 80
在inspect模块中的_ParameterKind类中,有五种类型的参数:
1.POSITIONAL_OR_KEYWORD
位置参数或关键字参数,绝大部分的函数都具有这一类型的参数。
2.VAR_POSITIONAL
位置参数,这些位置参数形成了tuple
3.VAR_KEYWORD
关键字赋值类型参数,这些参数形成了字典
4.KEYWORD_ONLY
只能是关键字参数,python3中新出现的类型
5.POSITIONAL_ONLY
只能是位置参数。现在的python函数定义语法并不支持这一类型。
但是例外存在于C实现的函数,比如divmod,这个函数不支持关键字函数。
my_tag = {'text': 'img', 'max_len': 80}
bound_args = sig.bind(**my_tag)
bound_args
<inspect.BoundArguments at 0x475cba8>
for name, value in bound_args.arguments.items():
print("{}={}".format(name, value))
text=img
max_len=80
del my_tag['max_len']
sig.bind(**my_tag) # that's ok the max_len has default value 80
<inspect.BoundArguments at 0x44c3400>
my_tag
{'text': 'img'}
my_tag['max_len'] = 80
del my_tag['text']
sig.bind(**my_tag) # error! need the value of text
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
C:\Python34\lib\inspect.py in _bind(self, args, kwargs, partial)
2532 try:
-> 2533 arg_val = next(arg_vals)
2534 except StopIteration:
StopIteration:
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-49-1c401fb09162> in <module>()
----> 1 sig.bind(**my_tag)
C:\Python34\lib\inspect.py in bind(*args, **kwargs)
2650 if the passed arguments can not be bound.
2651 '''
-> 2652 return args[0]._bind(args[1:], kwargs)
2653
2654 def bind_partial(*args, **kwargs):
C:\Python34\lib\inspect.py in _bind(self, args, kwargs, partial)
2569 msg = '{arg!r} parameter lacking default value'
2570 msg = msg.format(arg=param.name)
-> 2571 raise TypeError(msg) from None
2572 else:
2573 # We have a positional argument to process
TypeError: 'text' parameter lacking default value