對象也可以當(dāng)方法用?

1、問題

我剛開始接觸爬蟲的時候,只是看完了 python 的基礎(chǔ),對 python 的語法還沒有一個很深入的了解,在使用 bs4 這個庫的時候,對其中某些語法感到非常的驚奇,不明白是怎么實現(xiàn)的。

bs4 的官方文檔中說到:find_all() 幾乎是 Beautiful Soup 中最常用的搜索方法,所以我們定義了它的簡寫方法。BeautifulSoup 對象和 tag 對象可以被當(dāng)作一個方法來使用,這個方法的執(zhí)行結(jié)果與調(diào)用這個對象的 find_all() 方法相同,下面兩行代碼是等價的:

soup.find_all("a")
soup("a")

這里,soup 是一個 BeautifulSoup 對象,soup("a") 這很明顯是把對象當(dāng)方法使用了,這是怎么做到的呢?

2、實現(xiàn)

在 Python 中,除了用戶定義的函數(shù),調(diào)用運算符(即 ())還可以應(yīng)用到其他對象上。內(nèi)置的 callable() 函數(shù)用來判斷一個對象能否調(diào)用。就是說,任何 Python 對象都可以表現(xiàn)得像函數(shù)一樣,為此,只需實現(xiàn)實例方法 __call__。

來看一個簡單的示例:

class Sum:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    def add(self):
        return self._x + self._y

    def __call__(self):
        return self.add()


sum = Sum(1, 2)

print(sum.add())
print(sum())
print(callable(sum))

輸出:

3
3
True

這樣就明白了,bs4 中亦是如此,源碼如下:

class Tag(PageElement):
    def __call__(self, *args, **kwargs):
        return self.find_all(*args, **kwargs)

這背后涉及到的概念叫做可調(diào)用對象,Python 數(shù)據(jù)模型文檔列出了 7 種可調(diào)用對象。

  • 用戶定義的函數(shù):使用 def 語句或 lambda 表達(dá)式創(chuàng)建。
  • 內(nèi)置函數(shù):使用 C 語言(CPython)實現(xiàn)的函數(shù),如 len 或 time.strftime。
  • 內(nèi)置方法:使用 C 語言實現(xiàn)的方法,如 dict.get。
  • 方法:在類的定義體中定義的函數(shù)。
  • :調(diào)用類時會運行類的 __new__ 方法創(chuàng)建一個實例,然后運行 __init__ 方法,初始化實例,最后把實例返回給調(diào)用方。因為 Python 沒有 new 運算符,所以調(diào)用類相當(dāng)于調(diào)用函數(shù)。(通常,調(diào)用類會創(chuàng)建那個類的實例,不過覆蓋 __new__ 方法的話,也可能出現(xiàn)其他行為。)
  • 類的實例:如果類定義了 __call__ 方法,那么它的實例可以作為函數(shù)調(diào)用。
  • 生成器函數(shù):使用 yield 關(guān)鍵字的函數(shù)或方法。調(diào)用生成器函數(shù)返回的是生成器對象。

轉(zhuǎn)自 https://juejin.im/post/5cc2a673f265da03b2043673

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容