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
相關文章
相關標籤/搜索