Functions vs. Methods

初学者包括本人在内对Function和Method容易混淆,所以特意花了点时间查阅相关资料梳理一下它们的区别,通过Code实践更能体会其中的不同。

查看官网定义
函数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参数代表对象本身,即总是指调用时的类的实例

扫描二维码关注公众号,回复: 12718882 查看本文章
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

猜你喜欢

转载自blog.csdn.net/wumingxiaoyao/article/details/108937999