function vs method in python
function和对象无关,function需要的所有参数都需要显式传递
method是面向对象编程的一个概念,是绑定在对象上的function,method需要的参数是可以隐式传递的
method本质上仍然是function
instance method
定义在python class内的、不被装饰的function,对class而言是function,对instance而言是method
例如下面定义在class C内部的function f,对C而言(C本身也是一个object),f是它的一个attribute;而对于C()而言f就是instance method
(注意,Python 是没有 self
cls
关键字的,self
完全可以换成this
。这里的形参self
接受一个具体的实例)
>>> class C:
... def f(self):
... print(self.name)
...
>>> print(C.f)
<function C.f at 0x10958a040> # C.f is a normal function, is an attribute of class C
>>> print(C().f)
<bound method C.f of <__main__.C object at 0x10951dc10>> # C().f is a method bound to instance
>>>
>>> c = C()
>>> c.name = "test"
>>> c.f()
test
>>> C.f(c)
test
>>> # c.f() is totally equal to C.f(c)
-
C.f
is a normal function to C, whileC().f
is a method to C(). -
c.f()
is totally equal toC.f(c)
.c.f()
本质上是调用了C.f(c)
,但c.f()
不需要传值给f
的参数self
,这就是参数的隐式传递
staticmethod
定义在python class内的、被@staticmethod
装饰的function,就是staticmethod
顾名思义,静态方法,定义时是什么样,使用时就是什么样,和普通function无异
一般地,staticmethod多用于普通的、绑在类或者实例上的 helper func
静态方法作为类的一个属性存在,但是类、类实例(类实例在查找属性时可以向上搜寻到类内部)都可以调用
@staticmethod
会让C.f
和C().f
都返回function而不是method
也就是,@staticmethod
不改变C.f
,而改变C().f
如下,不管是类调用还是实例调用,都必须完整地显式传参,是一个普通的function
>>> class C:
... @staticmethod
... def f(name:str):
... print(name)
...
>>> print(C.f)
<function C.f at 0x7ff277b74a60>
>>> print(C().f)
<function C.f at 0x7ff277b74a60>. # C().f is a function
>>> C.f("test")
test
>>> C().f("test")
test
>>>
staticmethod的实现
要实现staticmethod可以依托于描述符的机制,在__get__
中返回原始的函数,因此它的 Python 实现版本异常的简单:
class staticmethod(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return self.f # 原封不动把f return回去
classmethod
定义在python class内的、被@classmethod
装饰的function,就是classmethod
@classmethod
会让C.f
和C().f
都返回绑在类上的method(类本身也是object,也可以绑方法),而不是function
>>> class C:
... @classmethod
... def f(cls):
... print(cls, cls.__name__)
...
>>> print(C.f)
<bound method C.f of <class '__main__.C'>>
>>> print(C().f)
<bound method C.f of <class '__main__.C'>>
>>> C.f()
<class '__main__.C'> C
>>> C().f()
<class '__main__.C'> C
classmethod的实现
同样依托于描述符的机制,读取时通过__get__
中将function转化为method
import types
class classmethod(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
return types.MethodType(self.f, klass)
网友评论