Python: 無參數的函數裝飾器

寫帶參數的函數裝飾器最糾結的是須要包好多層,最外層是接收參數的函數,它返回一個接收函數的的函數。但這樣有個問題是,最終包裝出來的裝飾器必須加()調用一下,即便沒有參數也須要這樣作,由於調用這個最外層函數才能返回裏面裝飾器(就是接收函數的函數)。之前一篇爲例,能夠這樣改進:html

def opt_arguments(func):
	def meta_wrapper(*args, **kwargs):
		if len(args) == 1 and callable(args[0]):
			return func(args[0])
		else:
			def meta_func(inner_func):
				return func(inner_func, *args, **kwargs)
			return meta_func
	return meta_wrapper

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

	@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

這樣獲得的annotation能夠無參數使用:app

image

相關文章
相關標籤/搜索