python中的綁定方法和未綁定方法是什麼?
bound和unbound方法是個很簡單的概念。在許多語言當中,類似於a.b()這樣的調用方法是一個整體,但在Python中,它其實是兩部分:獲取屬性a.b,調用()。所以也可以寫成:
c = a.b
c()
跟直接調用a.b()是等效的。當a是某個類的實例,b是這個類的方法的時候,a.b的返回值就是bound method,也就是綁定方法。它實際上是個bound method對象,這個對象提前將self參數進行了綁定。實際演示一下就很容易懂了:
&>&>&> class A(object):
... def b(self):
... pass
...
&>&>&> a = A()
&>&>&> a.b
&
&>&>&> A.b
&
&>&>&>
相應的unbound method是沒有綁定self的對象。在Python 3中,它就是普通的函數,在Python 2中則是unbound method類型,不過區別不大。
我們知道像A.b這樣的方法實際上跟一個普通定義的函數沒有本質區別,這個函數有一個參數self,所以實際上完全可以用A.b(a)的方式來調用,也就是手工將self參數指定為a。這也就是unbound method的用法。而相應的,bound method是一個實現了__call__的對象,它自動將調用這個對象的過程重定向到A.b(a)上面,相當於通過functools.partial綁定了第一個參數的效果,所以叫做bound method。內部實現機制上來說,類的方法通過descriptor機制在運行時返回bound method對象,跟@property 本質上是一樣的,參考以前寫的另一篇答案 Python @property使用的問題?- 描述符
描述符實現了__get__,__set__,__delete__方法。如果實現了__set__,就稱為數據描述符;否則稱為非數據描述符。classmethod,staticmethod,函數為非數據描述符;property為數據描述符。下面為一個例子:
class staticmethod(object):
"reconstruct __builtins__.staticmethod"
def __init__(self, f):
self.f = f
def __get__(self, obj, typ=None):
return self.f
- Understanding __get__ and __set__ and Python descriptors
- 如何理解 Python 的 Descriptor?
- 函數
上面說了函數是一個描述符,那它肯定實現了__get__方法。
&>&>&> def f(x):
return x
&>&>&> f.__get__ 所以__get__的第一個參數為None的時候就返回unbound method;否則就返回bound method。
&
&>&>&> f.__get__(None, 1)
&
&>&>&> f.__get__(1, 1)
&
- 類中的方法
class classmethod(object):
"reconstruct __builtins__.classmethod"
def __init__(self, f):
self.f = fdef __get__(self, obj, typ=None):
return self.f.__get__(typ, type)class staticmethod(object):
"reconstruct __builtins__.staticmethod"
def __init__(self, f):
self.f = fdef __get__(self, obj, typ=None):
return self.fclass A(object):
a = 1
def __init__(self):
self.b = 2# instance method
def f(self):
return self.b# class method
@classmethod
def g(cls):
return cls.a# static method
@staticmethod
def h():
return 3
類和類的實例在調用
- 實例方法,將調用函數的__get__;
- 類方法,將調用classmethod的__get__;
- 靜態方法,將調用staticmethod的__get__。
具體過程如下
&>&>&> A.f # 等價於 A.__dict__[f].__get__(None, A)
&
&>&>&> A().f # 等價於 A.__dict__[f].__get__(A(), A)
&
&>&>&> A.g # 等價於 A.__dict__[g].__get__(None, A)
&
&>&>&> A().g # 等價於 A.__dict__[g].__get__(A(), A)
&
&>&>&> A.h # 等價於 A.__dict__[h].__get__(None, A)
&
&>&>&> A.h # 等價於 A.__dict__[h].__get__(A(), A)
&
你把上述等價式結合上函數,classmethod和staticmethod的__get__就知道什麼時候返回unbounded method,什麼時候返回bounded method。
- 如何理解 Python 的 Descriptor?
python 2 中,所謂綁定,就是方法必須是類生成的實例對象,才能調用的方法,也就是實例方法。
詳細請看《python核心編程第2版》350頁。
綁定方法,就是該方法必須和具體的某個類對象進行綁定!同一個類中可以有無數多個對象,某個方法又必須與一個實例對象綁定,故叫綁定方法。
推薦閱讀:
※在python 中如何將 list 轉化成 dictionary
TAG:Python |