============================ 9.1 åœ¨å‡½æ•°ä¸Šæ·»åŠ åŒ…è£…å™¨ ============================ ---------- 问题 ---------- ä½ æƒ³åœ¨å‡½æ•°ä¸Šæ·»åŠ ä¸€ä¸ªåŒ…è£…å™¨ï¼Œå¢žåŠ é¢å¤–çš„æ“作处ç†(比如日志ã€è®¡æ—¶ç‰)。 ---------- 解决方案 ---------- å¦‚æžœä½ æƒ³ä½¿ç”¨é¢å¤–的代ç 包装一个函数,å¯ä»¥å®šä¹‰ä¸€ä¸ªè£…饰器函数,例如: .. code-block:: python import time from functools import wraps def timethis(func): ''' Decorator that reports the execution time. ''' @wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(func.__name__, end-start) return result return wrapper 下é¢æ˜¯ä½¿ç”¨è£…饰器的例å: .. code-block:: python >>> @timethis ... def countdown(n): ... ''' ... Counts down ... ''' ... while n > 0: ... n -= 1 ... >>> countdown(100000) countdown 0.008917808532714844 >>> countdown(10000000) countdown 0.87188299392912 >>> ---------- 讨论 ---------- 一个装饰器就是一个函数,它接å—一个函数作为å‚数并返回一个新的函数。 å½“ä½ åƒä¸‹é¢è¿™æ ·å†™ï¼š .. code-block:: python @timethis def countdown(n): pass è·Ÿåƒä¸‹é¢è¿™æ ·å†™å…¶å®žæ•ˆæžœæ˜¯ä¸€æ ·çš„: .. code-block:: python def countdown(n): pass countdown = timethis(countdown) 顺便说一下,内置的装饰器比如 ``@staticmethod, @classmethod,@property`` 原ç†ä¹Ÿæ˜¯ä¸€æ ·çš„。 例如,下é¢è¿™ä¸¤ä¸ªä»£ç 片段是ç‰ä»·çš„: .. code-block:: python class A: @classmethod def method(cls): pass class B: # Equivalent definition of a class method def method(cls): pass method = classmethod(method) 在上é¢çš„ ``wrapper()`` 函数ä¸ï¼Œ 装饰器内部定义了一个使用 ``*args`` å’Œ ``**kwargs`` æ¥æŽ¥å—ä»»æ„å‚数的函数。 在这个函数里é¢è°ƒç”¨äº†åŽŸå§‹å‡½æ•°å¹¶å°†å…¶ç»“果返回,ä¸è¿‡ä½ 还å¯ä»¥æ·»åŠ 其他é¢å¤–的代ç (比如计时)。 然åŽè¿™ä¸ªæ–°çš„函数包装器被作为结果返回æ¥ä»£æ›¿åŽŸå§‹å‡½æ•°ã€‚ 需è¦å¼ºè°ƒçš„是装饰器并ä¸ä¼šä¿®æ”¹åŽŸå§‹å‡½æ•°çš„å‚æ•°ç¾å以åŠè¿”回值。 使用 ``*args`` å’Œ ``**kwargs`` 目的就是确ä¿ä»»ä½•å‚数都能适用。 而返回结果值基本都是调用原始函数 ``func(*args, **kwargs)`` 的返回结果,其ä¸func就是原始函数。 刚开始å¦ä¹ 装饰器的时候,会使用一些简å•çš„例åæ¥è¯´æ˜Žï¼Œæ¯”如上é¢æ¼”示的这个。 ä¸è¿‡å®žé™…场景使用时,还是有一些细节问题è¦æ³¨æ„的。 比如上é¢ä½¿ç”¨ ``@wraps(func)`` 注解是很é‡è¦çš„, 它能ä¿ç•™åŽŸå§‹å‡½æ•°çš„元数æ®(下一å°èŠ‚会讲到),新手ç»å¸¸ä¼šå¿½ç•¥è¿™ä¸ªç»†èŠ‚。 接下æ¥çš„å‡ ä¸ªå°èŠ‚æˆ‘ä»¬ä¼šæ›´åŠ æ·±å…¥çš„è®²è§£è£…é¥°å™¨å‡½æ•°çš„ç»†èŠ‚é—®é¢˜ï¼Œå¦‚æžœä½ æƒ³æž„é€ ä½ è‡ªå·±çš„è£…é¥°å™¨å‡½æ•°ï¼Œéœ€è¦è®¤çœŸçœ‹ä¸€ä¸‹ã€‚