Python 基础系列 9 - 函数和方法的区别 Functions vs. Methods

初学者包括本人在内对 Function 函数和 Method 方法容易混淆,所以特意花了点时间查阅相关资料梳理一下它们的区别,通过 Code 实践更能体会其中的不同。更多 Python 基础系列文章,请参考 Python 基础系列大纲

查看官网定义,函数Function(注意:定义中未说是定义在 class 类外的

A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body.

方法 Method(注意:一定是定义在 class 里的,强调 self 为第一参数

A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self).

我们还是通过 Code 来体会上述定义吧。

class TestClass:

    def normal_fun(self):
        return 'normal'

    @staticmethod
    def static_fun():
        return 'staticmethod'

    @classmethod
    def class_fun(cls):
        return 'classmethod'

print("------------------------------------class.method-------------------------------------")
print(TestClass.normal_fun)
print(TestClass.static_fun)
print(TestClass.class_fun)
print("------------------------------------instance.method-------------------------------------")
class_instance = TestClass()
print(class_instance.normal_fun)
print(class_instance.static_fun)
print(class_instance.class_fun)

从结果来看,不难发现类调用normalstatic 方法均为 Function类调用class 方法才为 Method; 实例调用normalclass 方法均为 Method实例调用static 方法为 Function

------------------------------------class.method-------------------------------------
<function TestClass.normal_fun at 0x00000209564CBE50>
<function TestClass.static_fun at 0x00000209564CBDC0>
<bound method TestClass.class_fun of <class '__main__.TestClass'>>
------------------------------------instance.method-------------------------------------
<bound method TestClass.normal_fun of <__main__.TestClass object at 0x00000209564E10D0>>
<function TestClass.static_fun at 0x00000209564CBDC0>
<bound method TestClass.class_fun of <class '__main__.TestClass'>>

@classmethod 下定义的方法属于 Method,@staticmethod 定义的方法属于 Function。
而类 class 中定义的普通方法要分是类调用还是类对象调用。
1.类调用:Function
2.类对象调用:Method

结论:
static 方法和类调用的 normal 方法均属于函数 Function,因为与类和实例无绑定关系;
class 方法和类实例调用的 normal 方法均为方法 Method,因为与类和实例有绑定关系。

为了深入理解,我们有必要知道 Python 中 normal,static,class 方法的区别。

Normal, static, class 方法的定义:

normal 实例方法
类的所有实例方法都必需至少带有一个名为 self 的参数,且必需是该方法的第一个形参(如果有多个形参),self 在定义时必须定义,但是调用时会自动传入。self 和对象指向同一个内存地址,self 参数代表对象本身,即总是指调用时的类的实例

class Test:
  def prt(self):
    print(self)
    print(self.__class__)
  
t = Test()
t.prt()

self 是实例对象本身

<__main__.Test object at 0x00000209563FA4F0>
<class '__main__.Test'>

子类实例用户用户方法时,看看 self 的指向

class Parent: 
    def pprt(self):
        print("call pprt()")
        print(self)
        print(self.__class__)

class Child(Parent):
    def cprt(self):
        print("call cprt()")
        print(self)
        print(self.__class__)
    
c = Child()
print("---------------child instance call------------------------")
c.cprt()
c.pprt()
p = Parent()
print("---------------parent instance call------------------------")
p.pprt()

c.pprt(),尽管是用户父类的方法,self 也是指向调用时 c 实例对象本身。

---------------child instance call------------------------
call cprt()
<__main__.Child object at 0x000002095651AD00>
<class '__main__.Child'>
call pprt()
<__main__.Child object at 0x000002095651AD00>
<class '__main__.Child'>
---------------parent instance call------------------------
call pprt()
<__main__.Parent object at 0x0000020956530430>
<class '__main__.Parent'>

staticmethod()

Transform a method into a static method.
A static method does not receive an implicit first argument. The @staticmethod form is a function decorator,
A static method can be called either on the class (such as C.f()) or on an instance (such as C().f()).

如果用了装饰器 @staticmethod,不需要表示自身对象的 self和自身类的 cls 参数,就跟使用函数一样,类和实例都可以调用。

classmethod()

A class method receives the class as implicit first argument, just like an instance method receives the instance.
A class method can be called either on the class (such as
C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.

而对于装饰器 @classmethod,它的第一个参数不是 self,是cls,它表示这个类本身。

code 实践:类调用各类型方法

class TestClass:

    def normal_fun(self):
        return 'normal'

    @staticmethod
    def static_fun():
        return 'staticmethod'

    @classmethod
    def class_fun(cls):
        return 'classmethod'
    
    def without_parameter():
        return 'without parameter'
    
print("TestClass.static_fun() result: " + TestClass.static_fun())
print("TestClass.class_fun() result: " + TestClass.class_fun())
print("TestClass.without_parameter() result: " + TestClass.without_parameter())
print("TestClass.normal_fun() result: " + TestClass.normal_fun())

类不能调用实例方法,其它方法均可以调用

#output:
TestClass.static_fun() result: staticmethod
TestClass.class_fun() result: classmethod
TestClass.without_parameter() result: without parameter

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-171-83e8b674ddfd> in <module>
     18 print("TestClass.class_fun() result: " + TestClass.class_fun())
     19 print("TestClass.without_parameter() result: " + TestClass.without_parameter())
---> 20 print("TestClass.normal_fun() result: " + TestClass.normal_fun())

TypeError: normal_fun() missing 1 required positional argument: 'self'

code 实践:实例对象调用各类型方法

class TestClass:

    def normal_fun(self):
        return 'normal'

    @staticmethod
    def static_fun():
        return 'staticmethod'

    @classmethod
    def class_fun(cls):
        return 'classmethod'
    
    def without_parameter():
        return 'without parameter'
        
test_instance = TestClass()
    
print("Testtest_instanceClass.static_fun() result: " + test_instance.static_fun())
print("test_instance.class_fun() result: " + test_instance.class_fun())
print("test_instance.normal_fun() result: " + test_instance.normal_fun())
print("test_instance.without_parameter() result: " + test_instance.without_parameter())

实例对像不能调用无参数的类方法,其它方法均可以调用

#output:
Testtest_instanceClass.static_fun() result: staticmethod
test_instance.class_fun() result: classmethod
test_instance.normal_fun() result: normal

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-173-471a80f7df3b> in <module>
     21 print("test_instance.class_fun() result: " + test_instance.class_fun())
     22 print("test_instance.normal_fun() result: " + test_instance.normal_fun())
---> 23 print("test_instance.without_parameter() result: " + test_instance.without_parameter())

TypeError: without_parameter() takes 0 positional arguments but 1 was given
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值