自定义函数的特殊属性已经专门整理过一篇(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
能够经过对应的底层函数,访问函数的全部特殊属性。