装饰器的本质是一个高阶函数。以下一段代码,当你使用 @log 时,Python 会根据你是否传参来选择不同的执行路径:
情况 A:直接使用 @log (不带括号)
此时 x 接收的是函数本身(即 f)。
代码进入 if callable(x) 分支,直接返回包装后的函数。
情况 B:使用 @log(‘execute’) (带参数)
此时 x 接收的是字符串 ‘execute’。
代码进入 else: 分支,返回一个名为 decorate 的新装饰器,由它来接收函数 f2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import functoolsdef log (x ): if callable (x): @functools.wraps(x ) def wrapper (*args, **kw ): print ("call %s(): " % x.__name__) return x(*args, **kw) return wrapper else : def decorate (func ): @functools.wraps(func ) def wrapper2 (*args, **kw ): print ("call %s %s(): " % (x, func.__name__)) return func(*args, **kw) return wrapper2 return decorate @log def f (x ): return x ** 2 @log('execute' ) def f2 (x ): return x ** 3 class Student (object ): @property def score (self ): return self ._score @score.setter def score (self, value ): if not isinstance (value, int ): raise ValueError('score must be an integer!' ) if value < 0 or value > 100 : raise ValueError('score must between 0 ~ 100!' ) self ._score = value