python修饰器中被修饰函数带参数的执行过程

这是 tornado.web.py 文件中一段

@property
def cookies(self):
    """An alias for `self.request.cookies <.httputil.HTTPServerRequest.cookies>`."""
    return self.request.cookies

这个 cookie 函数是在一个类里面,这个 self 应该是调用这个 cookie 的那个对象
比如 a.cookies()self 就是那个 a
那么 cookies 作为修饰函数
比如修饰函数形式是这样(我在那个源码文件中没找到 property 这个函数。。)

def property(f1):
    def wrapper():
        ..
        return f1()
    return wrapper

则调用 cookies <=> 调用 property(cookies)
那么这个被修饰函数的参数 self 是怎么传进这个修饰函数里面的呢


ps: 我为什么在源码文件中没有找到那个 property() 修饰函数,我都用 ctrl+f 找也没找到
tornado.web.py源码地址

阅读 3.2k
1 个回答

你如果對於 decorator 還有疑問的話, 可以參考 這篇文章

關於 decorator, 基本上一共有三個函數:

  1. decorator: 裝飾器/修飾器/修飾函數

  2. orifunc: 原函數/被修飾函數

  3. wrapper: 新函數/取代函數

簡單地可以表達為:

def decorator(orifunc):
    # do something here (register...)
    def wrapper(*args, **kwargs):
        # do something before (preprocess)
        result = orifunc()
        # do something after (postprocess)
        return result
    return wrapper

他們的關係是:

wrapper = decorator(orifunc)

可以用甜頭寫法表示為:

@decorator
def orifunc(*args, **kwargs):
    # do something...

decorator 在執行裝飾的時候,只會將 orifunc 包裝並回傳, 其實就是用 wrapper 取代掉。

修飾這個步驟呼叫的的是 decorator, 傳遞的參數是 orifunc, 返回值是 wrapper, 這個時候 orifunc (或是他的包裝替代品 wrapper 都還沒被呼叫, 只有 decorator 被呼叫), 所以原函數 orifunc 的參數根本不會傳遞進修飾函數(decorator) 中。

只有當我們呼叫裝飾過後的函數 wrapper 時才需要傳入 orifunc 需要的參數 (orifuncwrapper 的參數介面應當一致)。

回到你的問題, 當 property 被呼叫的時候, 調用的函數是 property, 傳入的參數是原函數 cookies, 返回值是 wrapper, 這時跟 self 都還沒有關係。

當我們呼叫被修飾過的函數 wrapper(也就是property(cookies)) 才需傳入與 cookies 相同的參數, 此時 self 才被傳入。

self.cookies() <=> property(cookies)(self)
                   ^^^^^^^^^^^^^^^^^
                   修飾的這步尚與 self 無關
               <=> wrapper(self)
                   ^^^^^^^^^^^^^
                   調用 wrapper 時才與 self 有關

P.S. property 是 python 的內建函數, 並非 tornado 特有的東西, 你可以在 python doc 中找到說明。


我回答過的問題: Python-QA

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进