• 第7.14节 Python类中的实例方法详析


    第7.14节 Python类中的实例方法详析

    一、    实例方法的定义
    在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式:
    1.    类体中定义实例方法
    第一种方式很简单,就是在类体中定义,所有在类中定义的方法默认是实例方法。定义实例方法与定义函数基本相同,只是Python要求实例方法的第一个形参必须为self,也就是实例对象本身,因此实例方法至少应该有一个self参数。关于self的说明,请大家参考老猿前面的章节7.5 揭开Python类中self的面纱。如下例子:

    class MethodTest():
        def method1(self):print("in method1")

    2.    在类体外将一个函数直接赋值给一个对象实例
    Python 是动态语言,允许为对象动态增加方法,相关步骤如下:
    1)    按照实例方法定义形式在类体外定义一个函数,函数需要将self作为第一个参数;
    2)    使用“实例对象名.方法名=函数”方式在实例中增加方法。
    老猿认为,这种动态定义实例方法,本质上就是动态增加实例变量,只是这个实例变量比较特殊,是个函数类型,对应的赋值也是一个函数。因此上述方法定义的实例方法,与类体中定义的方法还是有差别的,对这种方法Python 不会将实例对象自动绑定到方法的第一个参数,即使将第一个参数命名为 self 也没有用。
    3.    在类体外将一个函数绑定到对象实例
    这种方法与第二种方法本质上是一致的,只是能解决调用时无法自动将实例对象作为第一个实参处理的问题。具体绑定方法如下:
    1)    按照实例方法定义形式在类体外定义一个函数,函数需要将self作为第一个参数;
    2)    使用“实例对象名.方法名 = MethodType(函数, 对象)” 方式在实例中增加方法。
    其中MethodType是从Python的types模块import进来的,通过MethodType可以将函数与实例对象的某个方法进行绑定,调用时就无需再传递实例对象到第一个参数。

    上述第二种和第三种方法都是动态方法,绑定的“实例对象名.方法名”可以是一个已经存在的实例方法,也可以是新定义的一个属性方法,如果是一个已经存在的实例方法,新绑定的函数将替换原实例的方法。

    二、    实例方法的使用
    1.    实例方法可以在类体的实例方法内调用,此时调用方使用“self.方法”方式调用,并在调用传递实参时不需要使用self。请看如下类的定义和调用:

    class MethodTest():
        def method1(self):print("in method1")
        def method2(self):
            print("in method2")
            self.method1()

    上述代码中method2调用了方法method1,使用self方式调用。
    2.    在类体外面调用类体内直接定义的实例方法,直接用“实例名.方法名”方式调用,对于类体内定义的实例方法传实参时无需传递self形参对应的实参,由Python在编译时自动添加实例对象作为第一个实参。请看上面的类定义实例对象后调用method2:

    m1=MethodTest()
    m1.method2()

    上述样例代码执行截图:

    注意:在类外调用实例方法时,无需也不能传递self的实参,由Python解释器自动为其在后面执行时添加。如果定义的方法没有以类方法的方式定义,也没有在方法定义时将self作为第一个形参,编译时并不会报错,但调用该实例方法时会有运行时错误,因为Python会强行绑定实例对象作为第一个参数,因此调用者的实参与定义的形参是一样时,此时会多出一个实参self,导致执行时报参数个数不对的错误。
    3.    在类体外面调用通过函数直接赋值定义的实例方法时,其调用方式与类体内定义的模式不同,要求第一个实参必须是调用的对象本身;
    以上面的类MethodTest为例,如果要增加一个method3的实例方法,其代码如下:

    def dynamicmethond(self):print("in DynamicMethond")
    m1.method3=dynamicmethond

    这样m1这个实例就增加了一个method3方法,调用代码如下:
    m1.method3(m1)  #注意必须在第一个参数将实例自身传递进去

    4.    在类体外面调用通过MethodType绑定的实例方法时,其调用方式与类体内定义的模式相同,第一个形参self对应的实参无需传值,由Python自动添加对应的实例对象;
    以上面的类MethodTest为例,如果要增加一个method4的实例方法进行绑定,其代码如下:

    def dynamicmethond(self):print("in DynamicMethond")
    m1.method4= MethodType(dynamicmethond,m1)

    这样m1这个实例就增加了一个method4方法,且实现了方法与实例的绑定,调用代码如下:

    m1.method4()

    三、    构造方法
    之所以单独介绍构造方法,是因为构造方法是一个特殊的实例方法,具体特殊性包括如下:
    1.    Python的构造方法对所有自定义类名字都固定为__init__,且第一个参数必须为self;
    2.    可以允许开发者没有在类中定义构造方法,此时Python 会自动为该类定义一个只包含一个 self 参数的默认的构造方法;
    3.    构造方法如果有多个形参,除了第一个参数必须是self外,其他参数都是创建实例时在类名后面的括号中给出,也就构造方法的参数就是创建实例时传入的参数,也必须是创建实例时传入;
    4.    构造方法是每个实例定义时自动执行;
    5.    在子类重写构造方法时,必须调用超类(继承的类)的构造方法,否则可能无法正确地初始化对象。
    1)    Python3中所有类都继承于object类,构造函数的重写不用考虑object类的情况,即无需调用object类的构造函数;
    2)    在构造方法中调用父类的构造方法时,可以使用“父类.类名.__init__(self,其他参数)”的方式调用;
    3)    在构造方法中调用父类的构造方法时,可以使用“super().__init__ (参数)”的方式调用,注意此时的参数中不能传递self参数。但这种情况如果存在多个超类时,执行的是第一个超类的构造方法,其实参必须按照第一个超类构造方法的形参来传递,其他超类的构造方法必须通过“父类.类名.__init__(self,其他参数)”的方式调用。
    理解了这几点,结合其他语言的构造方法,就理解了Python的构造方法。

    四、    本节相关代码的完整执行截屏

    本节结合案例详细介绍了实例方法的定义和使用方法,需要注意,动态定义实例方法只影响单个实例自身,对其他实例没有影响。老猿认为动态定义实例方法的使用范围比较有限,如果可能尽量使用类体定义实例方法,仅在特定场景(如动态扩展功能)下使用动态实例方法。
    老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
    欢迎大家批评指正,谢谢大家关注!

  • 相关阅读:
    Android调用第三方so
    九度oj题目1518:反转链表
    九度oj题目1014:排名
    九度oj题目1012:畅通工程
    九度oj题目1027:欧拉回路
    九度oj题目1348:数组中的逆序对
    九度oj题目1521:二叉树的镜像
    九度oj题目1385:重建二叉树
    poj 1577 Falling Leaves
    poj 1321 棋盘问题
  • 原文地址:https://www.cnblogs.com/LaoYuanPython/p/11087700.html
Copyright © 2020-2023  润新知