<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你還分不清什么是方法(method),什么是函數(shù)(function)?

          共 5544字,需瀏覽 12分鐘

           ·

          2020-08-11 19:49

          點(diǎn)擊上方Python知識(shí)圈設(shè)為星標(biāo)

          回復(fù)1024獲取Python資料



          閱讀文本大概需要 5 分鐘


          點(diǎn)擊「閱讀原文」查看pk哥原創(chuàng)精品視頻。

          在編程語(yǔ)言中有兩個(gè)很基礎(chǔ)的概念,即方法(method)和函數(shù)(function)。如果達(dá)到了編程初級(jí)/入門級(jí)水平,那么你肯定在心中已有了初步的答案。

          也許在你心中已有答案了

          除去入?yún)ⅰ⒎祷刂怠⒛涿瘮?shù)之類的正確的形式內(nèi)容之外,你也許會(huì)說(shuō)“函數(shù)就是定義在類外面的,而方法就是定義在類里面的,跟類綁定的”。

          這種說(shuō)法有沒(méi)有問(wèn)題呢?當(dāng)然有!不然我就不會(huì)專門寫(xiě)這篇文章了,本文主要會(huì)來(lái)厘清這個(gè)問(wèn)題。

          在標(biāo)準(zhǔn)庫(kù)inspect 中,它提供了兩個(gè)自省的函數(shù),即 ismethod() 和 isfunction(),可以用來(lái)判斷什么是方法,什么是函數(shù)。

          因此,本文想要先來(lái)研究一下這兩個(gè)函數(shù),看看 Python 在處理方法/函數(shù)的概念時(shí),是怎么做的?

          關(guān)于它們的用法,先看一個(gè)最簡(jiǎn)單的例子:

          運(yùn)行的結(jié)果分別是“True”和“False”,表明我們所定義的 test() 是一個(gè)函數(shù),而不是一個(gè)方法。

          這兩個(gè)函數(shù)也可以用來(lái)檢測(cè)自身,不難驗(yàn)證出它們都是一種函數(shù):

          那么,接下來(lái)的問(wèn)題是:inspect 庫(kù)的兩個(gè)函數(shù)是什么工作原理呢?

          先來(lái)看看 inspect 中的實(shí)現(xiàn)代碼:

          在源碼中,我們看到了 isinstance() 函數(shù),它主要用于判斷一個(gè)對(duì)象(object)是否是某個(gè)類(class)的實(shí)例(instance)。

          我們還看到了 types.FunctionType 及types.MethodType ,它們指的就是目標(biāo)類。繼續(xù)點(diǎn)進(jìn)去看源碼:

          # 摘自 types.py
          def _f(): pass
          FunctionType = type(_f)

          class _C:
              def _m(self): pass
          MethodType = type(_C()._m)

          這里只是定義了兩個(gè)空的 _f() 和 _m(),然后就使用了內(nèi)置的 type() 函數(shù)。所以,我們完全可以把它們摘出來(lái),看看廬山真面目:

          梳理它們的關(guān)系,可以得到:

          經(jīng)過(guò)簡(jiǎn)化處理后,我們發(fā)現(xiàn)最關(guān)鍵的是兩個(gè)問(wèn)題:type() 函數(shù)如何判斷出一個(gè)對(duì)象是 function 或 method 類?instance() 函數(shù)如何判斷出一個(gè)對(duì)象是某個(gè)類的實(shí)例?

          這兩個(gè)內(nèi)置函數(shù)都是用 C 語(yǔ)言實(shí)現(xiàn)的,這里我就不打算繼續(xù)深究了……

          但是,讓我們?cè)倩仡^看看 inspect 中的注釋,就會(huì)注意到一些端倪:

          • isfunction() 判斷出的是用戶定義的函數(shù)(user-defined function), 它擁有__doc__、__name__ 等等屬性
          • ismethod() 判斷出的是實(shí)例方法(instance method), 它擁有函數(shù)的一些屬性,最特別的是還有一個(gè) __self__ 屬性

          還是注釋更管用啊,由此我們能得到如下的推論:

          1、非用戶定義的函數(shù),即內(nèi)置函數(shù),在 isfunction() 眼里并不是“函數(shù)”(FunctionType)!

          下面驗(yàn)證一下 len()、dir() 和 range():

          事實(shí)上,它們有專屬的類別(BuiltinFunctionType、BuiltinMethodType):

          特別需要注意的是,內(nèi)置函數(shù)都是builtin_function_or_method 類型,但是 range()、type()、list() 等看起來(lái)像是函數(shù)的,其實(shí)不然:

          (PS:關(guān)于這點(diǎn),我這篇文章 曾提到過(guò),就不再展開(kāi)了。)

          2、一個(gè)類的靜態(tài)方法,在 ismethod() 眼里并不是方法(MethodType)!

          創(chuàng)建了類的實(shí)例后,再看看:

          可以看出,除了 classmethod 之外,只有類實(shí)例的實(shí)例方法,才會(huì)被 ismethod() 判定為真!而靜態(tài)方法,不管綁定在類還是實(shí)例上,都不算是“方法”!

          有沒(méi)有覺(jué)得很不可思議(或者有點(diǎn)理不清了)?

          好了,回到本文開(kāi)頭的問(wèn)題,我們最后來(lái)小結(jié)一下吧。

          若以 inspect 庫(kù)的兩個(gè)函數(shù)為判斷依據(jù),則 Python 中的“方法與函數(shù)”具有一定的狹義性。在判斷什么是函數(shù)時(shí),它們并不把內(nèi)置函數(shù)計(jì)算在內(nèi)。同時(shí),在判斷什么是方法時(shí),并非定義在類內(nèi)部的都算,而是只有類方法及綁定了實(shí)例的實(shí)例方法才算是“方法”。

          也許你會(huì)說(shuō),inspect 的兩個(gè)判斷函數(shù)并不足信,內(nèi)置函數(shù)也應(yīng)該算是“函數(shù)”,類里面的所有方法都應(yīng)該算是“方法”。

          我承認(rèn)這種說(shuō)法在廣義上是可接受的,畢竟我們一直叫的就是“XX函數(shù)”、“XX方法”嘛。

          但是,理論和廣義概念只是方便人們的溝通理解,而代碼實(shí)現(xiàn)才是本質(zhì)的區(qū)別。也就是說(shuō),Python 在實(shí)際區(qū)別“方法與函數(shù)”時(shí),并不是文中開(kāi)頭的簡(jiǎn)單說(shuō)法,還有更多的細(xì)節(jié)值得關(guān)注。

          看完本文,你有什么想法呢?歡迎一起交流。



             
          -----------------------
          公眾號(hào):Python知識(shí)圈
          博客:www.pyzhishiquan.com
          知乎Python知識(shí)圈
          微信視頻號(hào):菜鳥(niǎo)程序員 (分享有趣的編程技巧、Python技巧)
          bilibili:菜鳥(niǎo)程序員的日常(目前原創(chuàng)視頻:22,累計(jì)播放量:75萬(wàn))


          我的微信視頻號(hào)定時(shí)更新中,近期真人出鏡分析講解 Python 經(jīng)典習(xí)題,后續(xù)會(huì)分享更多的干貨,歡迎關(guān)注我的微信視頻號(hào)。

             


          Python知識(shí)圈公眾號(hào)的交流群已經(jīng)建立,群里可以領(lǐng)取 Python 和人工智能學(xué)習(xí)資料,大家可以一起學(xué)習(xí)交流,效率更高,如果是想發(fā)推文、廣告、砍價(jià)小程序的敬請(qǐng)繞道一定記得備注「交流學(xué)習(xí)」,我會(huì)盡快通過(guò)好友申請(qǐng)哦!通過(guò)好友后私聊我「學(xué)習(xí)資料」或者「進(jìn)群」都可以。

          掃碼添加,備注:交流學(xué)習(xí)




          往期推薦
          01

          公眾號(hào)所有文章匯總導(dǎo)航(2-10更新)

          02

          Github上有趣的100個(gè)Python項(xiàng)目

          03

          打基礎(chǔ)一定要吃透這12類 Python 內(nèi)置函數(shù)


          我就知道你“在看”

          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩免费黄色 | 欧美午夜操逼大片 | AⅤ在线观看视频 | 一级特黄色片 | 激情影院tiantang |