Python 程序设计讲义(69):面向对象程序设计------类的定义与使用
目录
- [Python 程序设计讲义(69):面向对象程序设计------类的定义与使用](#Python 程序设计讲义(69):面向对象程序设计——类的定义与使用)
面向对象程序设计(Object Oriented Programming,OOP)是相对于结构化程序设计而言的。对象可以看作是数据以及可以操作这些数据的一系列方法的集合。面向对象程序编程主要针对大型软件设计而提出的,可以使软件设计更加灵活,并且能更好地进行代码复用。
一、面向对象程序设计的基本特征
面向对象程序设计方法具备以下三个特征:
1、封装性(encapsulation)
将一些数据和这些数据有关的操作集合在一起,形成一个实体------对象。用户只需要根据对象提供的外部接口访问对象即可,而不需要知道对象内部的具体细节。
封装的目的在于将对象的用户与设计者分开,用户必须知道对象的细节,只需用设计者提供的接口去操作对象。封装性使对象以外的事物不能随意获取对象的内部属性(公共属性除外),有效地避免了外部错误对它产生的影响,大大减轻了软件开发过程中查错的工作量,降低了排除错误的难度。隐蔽了程序设计的复杂性,提高了代码的重用性,降低了软件开发的难度。
2、继承性(inheritance)
在面向对象程序设计中,根据已有类(基类)可以派生出新类,称为类的继承性。
派生类无须重新定义在基类(又称为父类:parent)中已经定义的属性与行为,而是自动拥有父类的全部属性与行为。派生类既具有从父类继承过来的属性与行为,又具有自己新定义的属性与行为。继承机制实现了代码重用,有效缩短了程序的开发周期。
3、多态性(polymorphism)
多态性是指基类中定义的属性或行为,被派生类继承后,可以具有不同的数据类型或表现出不同的行为特性,使得同样的消息可以根据发送消息对象的不同而采用多种不同的行为方式。
二、类与对象的概念
类(class)是一系列具有相同特征和行为的事物的统称,是一个抽象的概念。类是封装对象的属性与行为的载体。具有相同属性和行为的一类实体称为类。Python使用class定义类,类名的首字母一般大写。
对象(object)表示任意存在的事物,通常将对象划分为两部分:静态部分与动态部分。静态部分称为属性,动态部分指对象的行为,即对象执行的动作。
在Python中,一切皆对象,字符串、列表等数据类型也具有与对象完全相似的用法。
每个对象都有一个类型,类是创建对象实例的模板,是对对象的抽象和概括。它包含对所创建对象的属性描述和行为特征的定义。类与对象的关系就是用类去创建(实例化)一个对象。
三、定义类与类的实例化
类表示具有相同属性和方法的对象的集合。需要先定义类,然后创建类的实例------对象。
在创建类时,用变量形式表示的对象属性称为数据成员或属性(成员变量),用函数形式表示的对象行为称为方法(成员函数)。成员属性和成员方法统称为类的成员。
1、定义类
定义类的语法结构如下:
python
class ClassName:
类体
参数说明:
(1)ClassName:用于指定类名,一般使用大写字母开头。如果类中包含两个或两个以上的单词,采用【驼峰式命名法】,即所有单词的首字母都采用大写。
(2)类体:主要由类成员(变量)、方法和属性等定义语句构成。
例如:定义一个学生(Student)类。
python
class Student:
pass
2、类的实例化:创建对象
对象是类的实例,只有创建了具体的对象,并通过【对象名.成员】的方式访问其中的数据成员或成员方法。
在类定义完成后,需要创建类的实例,即实例化该类的对象。
创建对象的语法如下:
python
ClassName(参数列表)
其中:ClassName是必选参数,用于指定具体的类。参数列表是可选的,当创建一个类时,如果没有创建__init__()方法,或__init__()方法只有一个self参数时,可不提供参数列表。
例如:定义一个对象zs,代码如下:
python
class Student:
pass
zs=Student()
print(type(zs))
print(zs)
程序的运行结果如下:
<class '__main__.Student'>
<__main__.Student object at 0x000001B0301E2A50>
从以上运行结果可以看出:zs是Student类的实例。
重新定义Student类,代码如下:
python
class Student:
def setName(self,name):
self.name=name
def getName(self):
return self.name
def greet(self):
print(f"Hello! My name is {self.name}")
zs=Student()
zs.setName(name="Zhangsan")
name=zs.getName()
print(name)
zs.greet()
程序的运行结果如下:
Zhangsan
Hello! My name is Zhangsan
四、构造函数与析构函数
1、构造函数:__init__()
构造函数(方法)是创建对象的过程中被调用的第一个方法。构造函数一般用于完成数据成员设置初值或必要的初始化工作。如果用户未设计构造函数,Python将提供一个默认的构造函数。构造函数的名称为__init__(),构造函数必须包含一个self参数,并且必须是第一个参数,self参数是一个指向实例本身的引用,用于访问类中的属性与方法,在方法调用时会自动传递实际参数self。
一个类定义了__init__()方法后,类实例化时就会自动为新生成的类实例默认调用__init__()方法,不需要手动调用。
python
class Student:
def __init__(self,name="Zhangsan"):
self.name=name
def setName(self,name):
self.name=name
def getName(self):
return self.name
zs=Student()
print(zs.getName())
lp=Student(name="Lipeng")
print(lp.getName())
lp.setName(name="Wangpeng")
print(lp.getName())
程序的运行结果如下:
Zhangsan
Lipeng
Wangpeng
构造方法包括创建对象与初始化对象。在Python中分两步执行:先执行__new__()方法,然后执行__init__()方法。
__init__()方法是当实例对象创建完成后被调用,然后设置对象属性的初始值。
__new__()方法是在实例创建之前被调用,创建实例然后返回该实例,__new__()方法是一个静态方法,至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python自动提供。__new__()方法必须有返回值,返回实例化出来的实例。
例如:
python
class Student:
def __init__(self):
print("__init__方法")
def __new__(cls):
print("__new__方法")
return object.__new__(cls)
zs=Student()
程序的运行结果如下:
__new__方法
__init__方法
2、析构方法:__del__
析构函数用来释放对象占用的资源,在Python收回对象空间之前自动执行。如果用户未设计析构函数,Python将提供一个默认的析构函数进行必要的清理工作。当删除对象时,Python会默认调用__del__方法。
python
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def getName(self):
return self.name
def getAge(self):
return self.age
def __del__(self):
print("__del__方法")
zs=Student(name="Zhangsan",age=20)
print(zs.getName())
print(zs.getAge())
del zs
程序的运行结果如下:
Zhangsan
20
__del__方法
五、创建类的方法与数据成员
类的成员主要由实例方法和数据成员(属性)组成。
1、创建实例方法
所谓实例方法,是指在类中定义的函数。该函数是一种在类的实例上操作的函数。实例方法的第一个参数必须是self。
创建实例方法的语法格式如下:
python
class 类名:
def 函数名(self,参数列表):
函数体
说明:
(1)函数名:一般以小写字母开头。
(2)self:表示类的实例,其名称可以是self以外的单词。
(3)参数列表:类成员的参数,多个参数用逗号隔开。
(4)函数体:实现函数的具体功能。
实例方法与普通函数的区别:
(1)函数实现的是某个独立的功能,实例方法是实现类中的一个行为,是类的一部分。
(2)类的方法必须有一个额外的第一个参数名称。按照惯例名称是self,self代表的是类的实例,代表当前对象的地址。self.class指向类。
实例方法创建完成后,可以通过类的实例名称和圆点操作符进行访问。
例如:
python
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def play(self,play_name):
print(f"{self.name}正在{play_name}")
zs=Student(name="Zhangsan",age=25)
zs.play(play_name="打篮球")
程序的运行结果如下:
Zhangsan正在打篮球
2、创建数据成员
数据成员是指在类中定义的变量,即属性。根据定义位置,属性有两种:一种是实例属性,一种是类属性。实例属性是在构造函数中定义的,类属性是在类中方法之外定义的属性。
(1)类属性
类属性是指定义在类中,并且在函数体外的属性。类属性属于类,可通过类名访问,也可以通过对象名访问,类属性可以在类的所有实例之间共享值,也就是可以在所有实例化的对象中公用。
例如:
python
class Student:
school="新乡市第一高中" #类属性
def __init__(self,name,age):
self.name=name
self.age=age
zs=Student(name="Zhangsan",age=25)
ls=Student(name="Lisi",age=22)
print(zs.school)
print(ls.school)
print(Student.school)
Student.phone="123456" #添加类属性
print(Student.phone)
print(zs.phone)
print(ls.phone)
Student.school="新乡市第二高级中学"#修改类属性的取值
print(zs.school)
print(ls.school)
程序的运行结果如下:
新乡市第一高中
新乡市第一高中
新乡市第一高中
123456
123456
123456
新乡市第二高级中学
新乡市第二高级中学
(2)实例属性
实例属性是指定义在方法中的属性,只作用于当前实例中。实例属性只能通过实例名访问。
对于实例属性可以通过实例名修改,与类属性不同,通过实例名修改属性后,并不影响该类的另一个实例中相应的实例属性的值。
例如:
python
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def setName(self,name):
self.name=name
def setAge(self,age):
self.age=age
zs=Student(name="Zhangsan",age=20)
print(zs.name,zs.age)
zs.setAge(age=22)
print(zs.name,zs.age)
zs.age=25
print(zs.name,zs.age)
程序的运行结果如下:
Zhangsan 20
Zhangsan 22
Zhangsan 25
(3)类属性和实例属性的区别
类属性相当于全局变量,为实例对象共有的属性,实例对象的属性为实例对象自己。
类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只有一个副本。
对于公有的类属性,在类外可以通过类对象和实例对象访问。例如:
python
class Student:
school="新乡市第一高中" #类属性
def __init__(self,name,age):
self.name=name
self.age=age
zs=Student(name="Zhangsan",age=25)
ls=Student(name="Lisi",age=22)
print(zs.school) #通过实例对象访问类属性
print(ls.school) #通过实例对象访问类属性
print(Student.school) #通过类对象访问类属性
程序的运行结果如下:
新乡市第一高中
新乡市第一高中
新乡市第一高中
如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方法修改的是实例属性,不会影响到类属性。并且之后如果通过实例对象去引用该名称的属性,实例属性会屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
即:类属性只能通过类对象修改,不能通过实例对象修改。如果通过实例对象修改类属性,其实是创建了一个同名的实例属性。
例如:
python
class Student:
school="新乡市第一高中" #类属性
def __init__(self,name,age):
self.name=name
self.age=age
zs=Student(name="Zhangsan",age=25)
ls=Student(name="Lisi",age=22)
Student.school="新乡市第二高级中学" #通过类对象修改类属性的值
print(Student.school)
print(zs.school)
print(ls.school)
print("="*30)
zs.school="新乡市实验中学" #通过实例修改类属性的值,其实是创建了一个同名的实例属性
print(Student.school)
print(zs.school)
print(ls.school)
程序的运行结果如下:
新乡市第二高级中学
新乡市第二高级中学
新乡市第二高级中学
==============================
新乡市第二高级中学
新乡市实验中学
新乡市第二高级中学