版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)
一般我们认为写在类中的是方法,写在外面的是函数。但这样说并不准确,下面将深入探讨方法和函数的区分:
在外部定义的是函数:
def func():
pass
print(func)
'''
<function func at 0x000001AC2340C1E0>
'''
在类内部定义的可以是方法:
# coding:utf-8
class Foo(object):
def f(self):
pass
obj = Foo()
print(obj.f)
'''
<bound method Foo.f of <__main__.Foo object at 0x00000254215AB1D0>>
'''
类调用静态方法,会把静态方法当作函数。所以,在类中定义的不一定是方法,还可以是函数:
# coding:utf-8
'''
定义在类中的还可以是函数
'''
class Foo(object):
def f(self):
pass
@staticmethod
def f2():
pass
obj = Foo()
print(Foo.f2) # 函数
print(obj.f2) # 函数
'''
<function Foo.f2 at 0x000001AF9471C7B8>
<bound method Foo.f of <__main__.Foo object at 0x000001AF9467B198>>
'''
再次探讨:使用类调用实例方法,会把实例方法当作函数,需要手动传self。所以,类中定义的也不一定是方法:
# coding:utf-8
class Foo(object):
def f1(self):
pass
@staticmethod
def f2():
pass
obj = Foo()
Foo.f1(obj) # obj需要自己传参
print(Foo.f1) # 把f1当作函数
obj = Foo()
obj.f1() # 不需要自己传参
print(obj.f1) # 把f1当作方法
'''
<function Foo.f1 at 0x000001F67119C730>
<bound method Foo.f1 of <__main__.Foo object at 0x000001F671193588>>
'''
准确判断是方法还是函数?
# coding:utf-8
from types import MethodType, FunctionType
def check(param):
if isinstance(param, MethodType):
print(param, 'is a method!')
elif isinstance(param, FunctionType):
print(param, 'is a function!')
else:
print('Others!')
class Foo(object):
def f1(self):
pass
@staticmethod
def f2():
pass
obj = Foo()
check(obj.f1) # 方法
check(Foo.f2) # 函数
check(obj.f2) # 函数
'''
<bound method Foo.f1 of <__main__.Foo object at 0x000001F62C49C198>> is a method!
<function Foo.f2 at 0x000001F62C4A1510> is a function!
<function Foo.f2 at 0x000001F62C4A1510> is a function!
'''
新的发现,对象调用的是方法,类调用的是函数,且函数需要手动传参:
# coding:utf-8
class Foo(object):
def f1(self):
pass
def f2(self):
pass
def f3(self):
pass
lst = [f1, f2]
obj = Foo()
obj.lst.append(obj.f3)
for item in Foo.lst:
print(item)
'''
<function Foo.f1 at 0x000001E53675C730>
<function Foo.f2 at 0x000001E53675C7B8>
<bound method Foo.f3 of <__main__.Foo object at 0x000001E536753588>>
'''
总结:一般我们认为在类中是方法,写在外面的是函数。其实,这样判断是函数还是方法是不精准的。方法和函数的区分,不仅和定义的位置有关系,还和方法或函数的调用者有关系。如果通过对象.xxx调用,那么xxx就是方法;如果通过类.xxx调用或者直接执行xxx,那么xxx就是个函数。面向对象中,方法中self不需要自己传参,而函数中每个参数都需要自己传参。