Python中的函數(function)與方法(method)使用詳解
在編程語言中有兩個很基礎的概念,即方法(method)和函數(function)。
除去入參、返回值、匿名函數之類的正確的形式內容之外,我們一般都會這樣說:“函數就是定義在類外面的,而方法就是定義在類里面的,跟類綁定的”
深究一下
判斷是函數(function)還是方法(method)
在標準庫inspect 中,它提供了兩個自省的函數,即 ismethod() 和 isfunction(),可以用來判斷什么是方法,什么是函數。
import inspect
def test1():
print('這是方法還是函數?')
print(inspect.isfunction(test1)) # True
print(inspect.ismethod(test1)) # False
運行的結果分別是“True”和“False”,表明我們所定義的 test() 是一個函數,而不是一個方法。
注意:不能用這種方式,這種方式會調用函數
import inspect
def test1():
print('這是方法還是函數?')
print(inspect.isfunction(test1()))
# 輸出結果
這是方法還是函數?
False
inspect.ismethod() 與 inspect.isfunction()
這兩個函數也可以用來檢測自身,不難驗證出它們都是一種函數
import inspect print(inspect.isfunction(inspect.ismethod)) # True print(inspect.isfunction(inspect.isfunction)) # True
那么,inspect 庫的兩個函數是什么工作原理呢?
看看源碼,將鼠標光標處放在要查看的內容上,按住Ctrl并單擊鼠標左鍵,進入源碼查看


通過 isfunction() 和 ismethod() 的注釋,我們可以得到以下結論:
- 非用戶定義的函數,即內置函數,在 isfunction() 眼里并不是“函數”(FunctionType)!
下面驗證一下 len()、 range():
import inspect print(inspect.isfunction(len)) # False print(inspect.isfunction(range)) # False
可以發(fā)現(xiàn),它們的本質并不是函數,事實上,它們有專屬的類別(BuiltinFunctionType、BuiltinMethodType)
print(type(len)) 輸出結果: <class 'builtin_function_or_method'>
內置函數都是builtin_function_or_method 類型
- 一個類的靜態(tài)方法,在 ismethod() 眼里并不是方法(MethodType)!
class MyTest():
@classmethod
def cls_func(cls):
pass
def ins_func(self):
pass
@staticmethod
def sta_func():
pass
print(inspect.ismethod(MyTest.cls_func)) # True
print(inspect.ismethod(MyTest.ins_func)) # False
print(inspect.ismethod(MyTest.sta_func)) # False
創(chuàng)建了類的實例后,再看看
test = MyTest() print(inspect.ismethod(test.cls_func)) # True print(inspect.ismethod(test.ins_func)) # True print(inspect.ismethod(test.sta_func)) # False
可以看出,除了 classmethod 之外,只有類實例的實例方法,才會被 ismethod() 判定為真!而靜態(tài)方法,不管綁定在類還是實例上,都不算是“方法”!
在源碼中,出現(xiàn)了 isinstance() 函數,它主要用于判斷一個對象(object)是否是某個類(class)的實例(instance)。
還出現(xiàn)了 types.FunctionType 及types.MethodType ,它們指的就是目標類。繼續(xù)點進去看源碼



經過簡化處理后,最關鍵是在于:通過type() 函數判斷出一個對象是 function 或 method 類,instance() 函數判斷出一個對象是否為某個類的實例
所以
isfunction() 判斷出的是用戶定義的函數(user-defined function), 它擁有__doc__、__name__ 等等屬性 ismethod() 判斷出的是實例方法(instance method), 它擁有函數的一些屬性,最特別的是還有一個 __self__ 屬性
若以 inspect 庫的兩個函數為判斷依據,則 Python 中的“方法與函數”具有一定的狹義性。
在判斷什么是函數時,它們并不把內置函數計算在內。同時,在判斷什么是方法時,并非定義在類內部的都算,而是只有類方法及綁定了實例的實例方法才算是“方法”。
也許你會說,inspect 的兩個判斷函數并不足信,規(guī)矩是寫死的,也有不靈活的時候,內置函數也應該算是“函數”,類里面的所有方法都應該算是“方法”。
這種說法在廣義上是可接受的,畢竟我們一直叫的就是“XX函數”、而不會去說“XX方法”。
但是,理論和廣義概念只是方便人們的溝通理解,而代碼實現(xiàn)才是本質的區(qū)別。
也就是說,Python 在實際區(qū)別“方法與函數”時,文中開頭所說:“函數就是定義在類外面的,而方法就是定義在類里面的,跟類綁定的”,這句話并沒有錯,但其中的細節(jié)還是值得關注的。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
PyTorch中dataloader制作自定義數據集的實現(xiàn)示例
本文主要介紹了PyTorch中dataloader制作自定義數據集的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-05-05
手把手教你pycharm專業(yè)版安裝破解教程(linux版)
這篇文章主要介紹了 手把手教你pycharm專業(yè)版安裝破解教程(linux版),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09
Python實現(xiàn)基于PIL和tesseract的驗證碼識別功能示例
這篇文章主要介紹了Python實現(xiàn)基于PIL和tesseract的驗證碼識別功能,結合實例形式分析了Python使用PIL與tesseract進行驗證碼識別操作的具體技巧與相關注意事項,需要的朋友可以參考下2018-07-07

