Python: 收集全部命名参数

有时候把Python函数调用的命名参数都收集到一个dict中能够更方便地作参数检查,或者直接由参数建立attribute等。更简单的理解就是def foo(*args, **kwargs): pass能够接受全部的参数,其中kwargs就是命名参数字典,那么直接在函数外面套个foo却不能达到目的,一个比较简单的实现是这样的:html

def annotation(**annotations):
	"""
	A decorator to collect all named args to function.__namedargs__,
	all anonymous args to function.__unnamedargs__,
	decorator's args to function.__annotations__.
	"""

	def func_decorator(func):
		@functools.wraps(func)
		def func_wrapper(*args, **kwargs):
			argspec = inspect.getargspec(func)
			namedargs = inspect.getcallargs(func, *args, **kwargs)

			# def foo(a, b=0, *c, **d): pass
			# foo(1, b=2, c=3, d=4) will convert c=3 to namedargs.
			unnamedargs = namedargs.pop(argspec.varargs, ())
			namedargs.update(namedargs.pop(argspec.keywords, {}))

			func_wrapper.__namedargs__ = namedargs
			func_wrapper.__unnamedargs__ = unnamedargs
			func_wrapper.__annotations__ = annotations
			func(*args, **kwargs)

		return func_wrapper

	return func_decorator

annotation的的用法仿照Python 3的Function Annotation,能够对参数作标记等,这里全部的标记都会存放在function.__annotations__中:app

image

若是只要annotation,那么能够这样作避免额外调用开销:函数

def annotation(**anno):
	"""
	A decorator to update decorator's args to function.__annotations__.

	"""

	def func_decorator(func):
		"""
		Static check annotation.
		"""
		argspec = inspect.getargspec(func)
		callargs = set(argspec.args)
		callargs.add(argspec.varargs)
		callargs.add(argspec.keywords)
		invalid_keys = anno.viewkeys() - callargs
		if invalid_keys:
			raise TypeError('Invalid annotation keys = %s' % (invalid_keys))
		else:
			func.__annotations__ = anno
			return func

	return func_decorator
相关文章
相关标签/搜索