第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的世界。
欢迎大家批评指正,谢谢大家关注!
第7.14节 Python类中的实例方法详析的更多相关文章
- 第8.14节 Python类中内置方法__str__详解
一. object类内置方法__str__和函数str 类的内置方法__str__和内置函数str实际上实现的是同一功能,实际上str调用的就是__str__方法,只是调用方式不同,二者的调用语法如下 ...
- 第8.12节 Python类中使用__dict__定义实例变量和方法
上节介绍了使用实例的__dict__查看实例的自定义属性,其实还可以直接使用__dict__定义实例变量和实例方法. 一. 使用__dict__定义实例变量 语法: 对象名. dict[属性名] = ...
- 第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析
第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析 静态方法也是通过类定义的一种方法,一般将不需要访问类属性但是类需要具有的一些能力可以静态方法提供. 一 ...
- 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑
上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...
- 第8.9节 Python类中内置的查看直接父类的__bases__属性
终于介绍完了__init__方法和__new__方法,接下来轻松一下,本节介绍类中内置的__bases__属性. 一. 语法释义 Python 为所有类都提供了一个 bases 属性,通过该属性可以查 ...
- 第8.4节 Python类中不是构造方法却胜似构造方法的__new方法__深入剖析:语法释义
一. 引言 在本博前面的内容都对构造方法__init__进行了介绍,也在前面章节引入了__new__方法,但老猿认为__new__方法比构造方法__init__更应该属于构造方法.这是因为在Py ...
- 第7.10节 Python类中的实例变量定义与使用
一. 引言 在前面章节已经引入介绍了类变量和实例变量,类体中定义的变量为类变量,默认属于类本身,实例变量是实例方法中定义的self对象的变量,对于每个实例都是独有数据,而类变量是该类所有实例共享 ...
- 第8.11节 Python类中记录实例变量属性的特殊变量__dict__
一. 语法释义 调用方法:实例. __dict__属性 __dict__属性返回的是实例对象中当前已经定义的所有自定义实例变量的名和值,用字典存储,每个元素为一个"实例变量名:值" ...
- 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解
上节介绍了__new__()方法这个比构造方法还重要的方法的语法,本节通过案例来详细剖析__new__()方法的细节以及它与构造方法之间的关系. 一. 案例说明 本节以圆Cir类为例来说明,为了 ...
随机推荐
- 震惊!很多人都不知道 CSS Grid 框架早就有了!
前言 写作本文起源于知乎的一个问题:[CSS Grid 布局那么好,为什么至今没有人开发出基于 Grid 布局的前端框架呢?] 这篇文章拖沓了两个月,是因为真的不知道从哪里说好.这个问题的所有回答几乎 ...
- 百度地图省市php获取
$api = 'http://api.map.baidu.com/shangquan/forward/?qt=sub_area_list&ext=1&level=3&areac ...
- Flink的sink实战之三:cassandra3
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Spark编程练习题
import org.apache.spark.sql.SparkSessionval spark = SparkSession.builder().appName("Spark SQL b ...
- 搭建面向NET Framework的CI/CD持续集成环境(一)
前言 网上大多数都是针对主流的Spring Cloud.NET Core的CI/CD方案.但是目前国内绝大部分的公司因为一些历史原因无法简单的把项目从NET Framework切换升级到NET Cor ...
- Docker - 解决创建 tomcat 容器镜像却无法访问页面的问题
问题背景 查看 tomcat 镜像 docker images 运行并创建 tomcat 容器 docker -d -p 8888:8080 --name=tomcat2 tomcat:latest ...
- IP 层收发报文简要剖析5--ip报文发送2
udp 发送ip段报文接口ip_append_data ip_append_data 函数主要用来udp 套接字以及raw套接字发送报文的接口.在tcp中发送ack 以及rest段的ip_send_u ...
- MVCC(转)
什么是 MVCC MVCC (Multiversion Concurrency Control) 中文全程叫多版本并发控制,是现代数据库(包括 MySQL.Oracle.PostgreSQL 等)引擎 ...
- Ceph根据Crush位置读取数据
前言 在ceph研发群里面看到一个cepher在问关于怎么读取ceph的副本的问题,这个功能应该在2012年的时候,我们公司的研发就修改了代码去实现这个功能,只是当时的硬件条件所限,以及本身的稳定性问 ...
- Proftp最简匿名访问配置
前言 每一次做ftp的配置都要弄半天,找文档,各种权限控制的坑,折腾半天,这次还是准备记录下来,以备不时之需,这里不配置什么高级的功能,就去实现一个最简单的配置 匿名用户的上传和下载 配置proftp ...