1
Python编程从入门到实践
1.12.1.2 8.1.2 类的实例对象和方法
8.1.2 类的实例对象和方法

程序想要完成具体的功能,仅有类是不够的,还需要根据类创建实例对象,通过实例对象完成具体的功能。

1.类的实例对象

实例对象就是为类创建一个具体的实例化的对象,以使用类的相关属性和方法。图8-5所示就是类、对象与实例的关系。

图8-5 类、对象与实例

Python中,创建类的实例化对象不需使用new,可以直接赋值,语法如下:

对象名=类名()

创建一个类的实例,使用类的名称,并通过__init__()方法接受参数,如例8.4所示。

【例8.4】创建类的对象实例。

以上实例输出结果如图8-6所示。

图8-6 输出结果

2.类的方法

在类的内部,使用def关键字可以为类定义一个方法。与一般函数定义不同,类方法必须包含参数self,且为第一个参数。

(1)构造方法

构造方法__init__()是一种特殊的方法,被称为类的构造函数或初始化方法,用来进行一些初始化的操作,在对象创建时就设置好属性。如果用户没有重新定义构造函数,则系统自动执行默认的构造方法。这个方法不需要显式调用,当创建了这个类的实例时,就会调用该方法。

在构造方法__init__()中,init前后用两个下划线开头和结尾,是Python内置的方法,用于在对象实例化时对实例进行的初始化工作。比如,显示一个姓名叫“张三”,学号是1号的学生,可以直接使用构造方法进行定义,如例8.5所示。

【例8.5】类的构造方法实例。

以上实例输出结果如图8-7所示。

图8-7 输出结果

在该例中,构造方法和自定义方法都有参数self。

self可以理解为“自己”,如同C++中类里面的this指针一样,就是对象自身的意思。在方法的定义中,第一个参数永远是self。某个对象调用其方法时,Python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。

self仅仅是一个变量名,也可以将self换为其他任意的名字,但是为了能够让其他开发人员能明白该变量的意思,一般都会把self当作名字。

在上例的构造方法中,直接给出了学生的姓名和学号。但实际上,对象的属性需要动态添加,在对象创建完成时确定对象的属性值。需要使用带参数的构造方法,在构造方法中传入参数设置属性的值,如例8.6所示。

【例8.6】带参数的构造方法操作实例。

以上实例输出结果如图8-8所示。

图8-8 输出结果

在上例中,empCount变量是一个类变量,它的值将在这个类的所有实例之间共享。在内部类或外部类使用“类名.属性”(Stu.empCount)访问。

在创建一个对象时,__init__()方法默认被调用,不需要手动调用。默认有1个参数名字为self。如果在创建对象时传递了两个实参,那么__init__(self)中除了self作为第一个形参外,还需要两个形参,例如__init__(self,name,stuid)。

__init__(self)中的self参数不需要开发者传递,Python解释器会自动把当前的对象引用传递进去。

(2)析构方法

__init__()方法是构造方法,当创建对象后,Python解释器会调用__init__()方法。当删除一个对象来释放类所占用的资源时,Python解释器会调用另外一个方法,也就是析构方法。

析构方法__del__()使用del命令,前后同样用两个下划线开头和结尾。该方法同样不需要显式调用,在释放对象时进行调用,可以进行释放资源的操作,如例8.7所示。

【例8.7】析构方法操作实例。

以上实例输出结果如图8-9所示。

图8-9 输出结果

上例中,执行到del stu语句时,删除stu对象并触发析构方法,显示“已释放资源”。但如果不执行del stu语句,换成delstu.name语句,则不会显示“已释放资源”,表明没有执行析构方法,因为此时stu对象存在,只不过stu的name属性被删除了。

析构方法必须是整个实例对象都被删除才能触发。

(3)类的封装

面向对象编程的特性是封装、继承与多态。封装是隐藏属性、方法与方法,并实现细节的过程。封装是在变量或方法名前加两个下划线,封装后,私有的变量或方法只能在定义它们的类内部调用,在类外和子类中不能直接调用。

封装的语法如下:

私有变量:__变量名

私有方法:__方法名()

通过设置私有变量或私有方法实现封装,在变量名或方法名前加上“”(两个下划线)。私有变量,可以避免外界对其随意赋值,保护类中的变量;私有方法,不允许从外部调用。对私有变量可以添加供外界调用的变通方法,用于修改或读取变量的值。私有方法和私有变量的操作如例8.8所示。

【例8.8】类的私有方法操作实例。

以上实例输出结果如图8-10所示。

图8-10 输出结果

Python不允许实例化的类访问私有数据,所以上例中最后一行代码报错。如果需要访问私有属性,可用object.className__attrName访问属性,将如下代码替换以上代码的最后一行:

print(counter._JustCounter__secretCount)

执行以上代码,结果如图8-11所示。

图8-11 执行结果