自定義函數的特殊屬性已經專門整理過一篇(Python 自定義函數的特殊屬性),方法的特殊屬性與其稍有不一樣,咱們經過下面這個例子展開介紹:python
class A(): def foo(self): '''a method''' print('hellow world!') bar = foo @classmethod def clsmtd(cls, arg): print(str(arg)) a = A()
與自定義函數的特殊屬性相比,實例方法具備 __self__
,__func__
這兩個函數所不具備的只讀屬性;此外,方法的 __doc__
,__name__
,__module__
也是隻讀。對於實例方法而言,其 __self__
屬性爲實例自己:segmentfault
print(a.foo.__self__) # <__main__.A object at 0x00000233DF6DE2E8> print(a) # <__main__.A object at 0x00000233DF6DE2E8>
而 __func__
屬性則返回方法所對應的底層函數:函數
print(a.foo) # <bound method A.foo of <__main__.A object at 0x00000233DF6DE2E8>> print(a.foo.__func__) #注意與 a.foo 的區別 # <function A.foo at 0x00000233DF6C3F28>
至於 __doc__
,__name__
,__module__
屬性則與函數相應屬性的值一致,所不一樣的是方法的這些屬性均爲只讀,不可改寫:code
print(a.foo.__doc__) # a method print(a.foo.__name__) # foo print(a.foo.__module__) # __main__
不過,實例方法也能夠經過其底層的 function
對象(經過 __func__
屬性得到)訪問函數所具備的特殊屬性,如:對象
print(a.foo.__func__.__code__) # <code object foo at 0x00000233DF6B5930, file "<ipython-input-43-c5636bcc492a>", line 3>
所以,諸如 __doc__
,__name__
,__module__
等屬性的值就能夠經過底層函數相應的特殊屬性進行改寫:ip
a.foo.__doc__ = 'raise error' # AttributeError: attribute '__doc__' of 'method' objects is not writable print(a.foo.__func__.__doc__) # a method a.foo.__func__.__doc__ = 'can be changed through func doc' print(a.foo.__doc__) # can be changed through func doc a.foo.__name__ = 'dobi' # AttributeError: 'method' object has no attribute '__name__' print(a.foo.__func__.__name__) # foo a.foo.__func__.__name__ = 'dobi' print(a.foo.__name__) # dobi
須要注意的是:當一個類的實例方法是經過其餘實例方法建立,則其餘實例方法所對應的底層函數並不是其所建立的實例方法,而是其所建立的實例方法所對應的底層函數:get
print(a.bar) #注意這裏 a.bar 是個實例方法 <bound method A.foo of <__main__.A object at 0x00000233DF6DE2E8>> print(a.bar.__func__) # <function A.foo at 0x00000233DF6C3F28>
上例中,經過其餘實例方法 a.bar
建立了實例方法 a.foo
,但a.bar.__func__
倒是 a.foo.__func__
而非 a.foo
:input
print(a.foo.__func__) # <function A.foo at 0x00000233DF6C3F28> print(a.foo) # <bound method A.foo of <__main__.A object at 0x00000233DF6DE2E8>>
實例方法執行時,其底層函數的首位參數爲實例自己,下面兩行代碼執行結果是一致的:it
a.foo() # hellow world! a.foo.__func__(a) # hellow world!
當一個實例方法(嚴格來講是類實例方法)是由類方法建立,則其 __self__
屬性是其類自己:io
print(a.clsmtd.__self__) # <class '__main__.A'>
事實上,經過類方法創建的(類)實例方法,在調用底層函數時(下例是 A.clsmtd.__func__
),其首位參數(也即 __self__
)是類自己,這一點與實例方法執行時有所區別。
a.clsmtd('dog') # dog A.clsmtd('dog') # dog A.clsmtd.__func__(A, 'dog') # dog
類實例方法,自己也是 bound method
,這與實例方法一致:
print(a.clsmtd) # <bound method A.clsmtd of <class '__main__.A'>> print(a.foo) # <bound method A.foo of <__main__.A object at 0x00000233DF6DE2E8>> print(A.clsmtd) # <bound method A.clsmtd of <class '__main__.A'>> print(A.foo) # <function A.foo at 0x00000233DF6C3F28>
只不過,一個是綁定類(類實例),另外一個是綁定實例。
Python 3 有兩種 bound method
, 一種是 instance method
,一種是 class method
(class instance method
),兩種均可以被實例訪問;
對於 instance method
其 __self__
屬性值爲 instance
自己,而 class method
其屬性值則爲 class
自己;
無論是 instance method
仍是 class method
,執行時,都須要調用與之對應的底層函數(underlying function
,經過 __func__
訪問),底層函數的首位參數經過 __self__
得到, 對於 instance method
其爲該實例自己,對於 class method
則爲該類自己;
bound method
能夠經過對應的底層函數,訪問函數的全部特殊屬性。