区分Python中的方法与函数 --Python3

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (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不需要自己传参,而函数中每个参数都需要自己传参。

猜你喜欢

转载自blog.csdn.net/Thanlon/article/details/94433438