内容正文:
专题十五 面向对象编程
[考纲要求]
1.了解面向对象的基本概念
2.熟记面向对象的特征
3.了解类的定义,能够创建类实现简单的编程
4.了解类属性和实例属性以及区别
5.熟记构造方法和析构方法的作用
6.了解类的单继承和多继承
[课时安排]
2课时
[知识梳理]
面向对象的基本概念
使用 Python 进行面向对象编程,需要先了解以下基本概念:
1.对象
对象是人们要进行研究的任何事物,对象不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象的状态和特征用数据值表示出来就是属性;对象的操作用于改变对象的状态,这些操作通过程序代码来实现的话就是方法。对象实现了数据和操作的结合。
2.类
类是对象的模版,比如:飞机的制造图纸就是类,有了飞机的制造图纸就能生产出一架飞机,这个飞机就是具体的对象。这里的图纸可以有属性(其实就是数据结构)和方法(其实就是函数)用于描述一组对象的共同属性和行为。类是对象的抽象化,对象则是类的具体化,是类的实例,一个类可以创建多个对象。
3.封装
封装是指将对象的数据(属性)和操作数据的过程(方法)结合起来所构成的单元,其内部信息对外界是隐藏的,外界不能直接访问对象的属性,而只能通过类对外部提供的接口对该对象进行各种操作,这样可以保证程序中数据的安全性。类是实施数据封装的工具,对象则是封装的具体实现,是封装的基本单位。定义类时将其成员划分为公有成员、私有成员,从而形成了类的访问机制,使得外界不能随意存取对象的内部数据(即成员属性和成员方法)。
4.继承
继承是指在一个类的基础上定义一个新的类,原有的类称为基类、超类或父类,新生成的类称为派生类或子类。子类不仅可以通过继承从父类中得到所有的属性和方法,也可以对所得到的这些方法进行重写和覆盖,还可以添加一些新的属性和方法,从而扩展父类的功能。
5.多态
多态是指一个名称相同的方法产生了不同的动作行为,多态可以通过覆盖和重载两种方式来实现,覆盖是指在子类中重新定义父类的成员方法,重载则是指允许存在多个同名函数,而这些函数的参数列表有所不同。
面向过程与面向对象的比较
在程序设计领域,存在着两种不同的程序设计方式,即面向过程编程和面向对象编程,面向过程编程就是通过算法分析列出解决问题所需要的操作步骤。
面向对象编程是一种以对象为基础,以事件或消息来驱动对象执行处理的程序设计方法,面向对象编程的主要特征是封装性、继承性、多态性。
Python 同时支持面向过程编程和面向对象編程。函数就是面向过程编程的基本单元。
面向对象编程是将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
对象与类
面向对象编程的基本步骤是:首先通过定义类来设置数据类型的数据和行为,然后基于该类创建对象,并通过存取对象的属性或调用对象的方法来完成所需操作。
类的定义
类可以通过 class 语句来定义,其语法格式如下:
class 类名:
类体
定义一个类时,以关键字 class 开始,后跟类名和冒号。类名遵循标识符(变量)命名规则,其首字母通常采用大写形式。
在类体中定义类的所有变量成员和函数成员。变量成员即类的属性,用于描述对象的状态和特征;函数成员即类的方法,用于实现对象的行为和操作。通过定义类可以实现数据和操作的封装。类体中也可以只包含一个 pass 语句,此时将定义一个空类。
在 Python 中,一切皆对象。定义了一个类对象,就可以通过类名和圆点运算符“.”来访问类的属性,其语法格式:类名.属性名
【示例】
class Student: # 定义Student类
name = "张三" # 定义类的属性
gender = "男"
age = 18
def hobby(self):
print("喜欢游泳")
# 访问类的属性
print("姓名:", Student.name)
print("性别:", Student.gender)
print("年龄:", Student.age)
创建对象(实例对象)
类是对象的模板,对象是类的实例。定义类之后,可以通过赋值语句来创建类的实例对象,其语法格式:对象名=类名(参数列表)
创建对象之后,该对象就拥有类中定义的所有属性和方法,此时可以通过对象名和圆点运算符“.”来访问这些属性和方法,也可以修改类属性(修改的类属性只能是当面对象使用),其语法格式如下:
对象名.属性名
对象名.方法名(参数)
对象名.属性名=值 # 修改类属性
【示例】利用类和对象计算圆的周长和面积
import math
class Circle:
radius = 0
def getPerimeter(self):
return 2 * math.pi * self.radius
def getArea(self):
return math.pi * self.radius ** 2
c1 = Circle() # 创建类的实例对象
c1.radius = 10 # 设置对象的属性值
# 调用类的方法
print(f"周长={c1.getPerimeter()},面积={c1.getArea()}")
c2 = Circle() # 再用类创建一个实例对象
c2.radius = 20 # 设置对象的属性值
# 调用类的方法
print(f"周长={c2.getPerimeter()},面积={c2.getArea()}")
属性
在类中定义的变量就是属性。属性按所属的对象可以分为类属性和实例属性,类属性是类对象所拥有的属性;实例属性是该类的实例对象所拥有的属性。
类属性
类属性按能否在类的外部访问可以分为公有属性和私有属性,通过在类中所有方法之外通过定义成员变量来创建,创建类之后也可以在类的外部通过类名和圆点运算符来添加公有属性。定义属性时,如果属性名以双下画线“__”开头,则该属性就是私有属性,在类中所有方法之外,无论是公有属性还是私有属性都可以直接访问,在类的成员方法内部则要通过“类名.属性名”形式来访问。在类的外部,公有属性仍然可以通过“类名.属性名”来访问,私有属性则不能通过这种形式来访问。如果试图通过“类名.属性名”来访问私有属性,系统则会发出 AttributeError 错误。
一般情况下,不允许也不提倡在类的外部访问类的私有属性。如果一定要在类的外部对类的私有属性进行访问,则需要使用一条下画线开头,后跟类名和私有属性名。例如: c1._MyClass__woman_avg_height 其中c1为实例对象,MyClass是类名,__woman_avg_height是私有属性。
【示例】创建一个MyClass类,访问公有和私有属性,以及类的方法。
class MyClass:
man = 18
woman = 12
man_avg_height = 175 # 以上为公有属性
__woman_avg_height = 165 # 定义私有属性
def class_info(self): # 定义类的方法
# 在类的方法中可以直接调用私有属性和公有属性
print(f"男生的人数:{self.man},男生的平均身高:{self.man_avg_height}")
print(f"女生的人数:{self.woman},女生的平均身高:{self.__woman_avg_height}")
c1 = MyClass() # 创建实例对象
# 访问类的公有属性
print(c1.man)
print(c1.woman)
print(c1.man_avg_height)
# 访问类的私有属性,需要使用一条下画线开头,后跟类名和私有属性名,才能访问。否则会出现 AttributeError 错误
print(c1._MyClass__woman_avg_height)
c1.class_info() # 访问类的成员方法
实例属性
实例属性是类的实例对象所拥有的属性,实例属性可以在类的内部或类的外部通过赋值语句来创建。
1)在类的内部,定义类的构造方法__init__或其他实例方法时,通过在赋值语句中使用self关键字、圆点运算符和属性名来创建类的属性,其语法格式如下:
self.属性名=值
其中 self 是类成员方法的第一个参数,代表类的当前实例。定义类的方法时,必须设置一个用于接受类的实例的参数,而且这个参数必须是第一个参数。在实例方法中,可以通过“self.属性名”形式来访问类的属性。
2)在类的外部(了解即可),创建类的实例对象后,可以通过在赋值语句中使用实例对象名、圆点运算符和属性名来创建新的实例属性,其语法格式如下:
实例对象名.属性名=值
【示例】请看下面的示例
class Car:
speed = 80 # 类属性
def __init__(self, brand, color):
self.brand = brand
self.color = color
def show(self):
print(f"车的品牌:{self.brand},车的颜色:{self.color},车的速度:{self.speed}")
c1 = Car("比亚迪", "白色")
c1.show()
c2 = Car("问界", "黑色")
c2.speed = 100 # 修改类属性
c2.show()
类属性与实例属性的比较
类属性与实例属性既相互区别又相互联系,搞清楚这种关系对掌握 Python 面向对象编程是很重要的。类属性与实例属性的区别表现在以下 3 个方面。
1)所属的对象不同:类属性属于类对象本身,可以由类的所有实例共享;实例属性则属于类的某个特定实例。如果存在同名的类属性和实例属性,则两者相互独立、互不影响。就是类似于全局变量和局部变量的关系。
2)定义的方法不同:类属性是在类中所有成员方法之外定义的,实例属性则是在构造方法__init__或其他实例方法中定义的。
3)引用的方法不同:类属性是通过“类名.属性名”形式引用的,实例属性则是通过“对象名.属性名”形式引用的。
方法
定义类时,除了定义成员属性外,还需要在类中定义一些函数,以便对类的成员属性进行操作。
在 Python 中,每当定义一个类时,系统都会自动地为它添加一些默认的内置方法,这些方法不需要显式调用,它们的命名也有特殊的约定。下面介绍两
个常用的内置方法,即构造方法和析构方法。
构造方法
构造方法_init_(self,[参数])是在创建新对象时被自动调用的,可以用来对类的实例对象进行一些初始化操作,例如设置实例属性。如果在类中未定义构造方法,则系统将执行默认的构造方法。构造方法支持重载,定义类时可以根据需要重新编写构造方法。
定义构造方法时,第一个参数为 self,这个名称只是一种习惯用法,也可以用其他名称,例如 this、me 等。self 参数用于接受类的当前实例,除了 self参数,如果构造方法包含其他参数,在创建类的新实例时必须提供,即写在类名后面的圆括号中。
【示例】构造方法示例
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def run(self):
print("{}的{}在行驶中...".format(self.color, self.brand))
if __name__ == '__main__':
car1 = Car("比亚迪", "黑色")
car1.run()
car2 = Car("问界", "白色")
car2.run()
析构方法
析构方法__del__(self)是在对象被删除之前被自动调用的,不需要在程序中显式调用,当程序运行结束时,在程序中创建的对象会被删除,此时系统会自动调用析构方法;当离开某个作用域(如函数)时,在该作用域中创建的对象会被删除,此时析构方法会被调用一次,这样可以来释放内存空间。析构方法支持重载,通常可以通过该方法执行一些释放资源的操作。
【示例】析构方法示例
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def run(self):
print("{}的{}在行驶中...".format(self.color, self.brand))
def __del__(self):
print("用来释放资源")
if __name__ == '__main__':
car1 = Car("宝马", "黑色")
car1.run()
car2 = Car("奔驰", "白色")
car2.run()
类的继承
继承是指在一个父类的基础上定义一个新的子类。子类通过继承从父类中得到所有的属性和方法,也可以对所得到的这些方法重写和覆盖,同时还可以添加一些新的属性和方法,从而拓展父类的功能。继承父类按父类的多少分为单继承和多继承,单继承是指子类从单个父类中继承,多继承则是指子类从多个父类中继承。
单继承
在python语言中,可以在单个父类的基础上来定义新的子类。这种继承关系称为单继承。单继承可以使用class语句来实现,其语法格式如下:
class 子类名(父类名):
类体
基于父类创建新的子类之后,改子类将拥有父类中的所有公有属性和所有成员方法,这些成员方法包括构造方法、析构方法等。
【示例】单继承示例
class Person:
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
def showInfo(self):
print("姓名:", self.name)
print("性别:", self.gender)
print("年龄:", self.age)
class Student(Person):
def say(self):
print("Hello World")
s1=Student("张三","男",18)
s1.showInfo() # 调用父类的方法
s1.say() # 调用自己的方法
多重继承
除了单一继承外,Python 还允许子类从多个父类继承,这种继承关系称为多重继承。与单一继承类似,多重继承也可以使用 class 语句来实现,其语法格式如下:
class 子类名(父类名1,父类名2,…):
类体
使用多继承经常需要面临的问题是,多个父类中包含同名的类方法。对于这种情况,Python 的处置措施是:根据子类继承多个父类时这些父类的前后次序决定,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法。示例:多重继承示例。
【示例】多继承演示:
class People:
def say(self):
print("hello world")
class Animal:
def say(self):
print("hello python")
class Person1(People, Animal):
pass
zhangsan = Person1()
zhangsan.say()
class Person2(Animal,People):
pass
lisi = Person2()
lisi.say()
[限时练习]
1. 在Python中,用于定义类的关键字是( )。
A. class
B. def
C. object
D. struct
【答案】A
【解析】定义类使用的关键字class
2. 在类中,用于定义类属性的变量位置是( )。
A. 在类的所有方法之外
B. 在类的方法内部
C. 在类的构造方法中
D. 在类的任意位置
【答案】A
【解析】类属性相当于全局变量和函数之间的关系,而类里面的方法其实就是函数
3. 在Python中,创建类的实例对象时,开始会自动调用的方法是( )。
A. __del__()
B. __init__()
C. main()
D. start()
【答案】B
【解析】__init__()是构造方法主要用于创建实例属性,一开始默认执行的方法
4. 在类中,用于定义私有属性的方式是( )。
A. 属性名前加单下划线
B. 属性名前加双下划线
C. 属性名后加单下划线
D. 属性名后加双下划线
【答案】B
【解析】属性名以双下画线“__”开头,则该属性就是私有属性
5. 在Python中,继承父类的子类定义方式是( )。
A. class 子类名 inherits 父类名:
B. class 子类名 extends 父类名:
C. class 子类名 implements 父类名:
D. class 子类名(父类名):
【答案】D
【解析】单继承可以使用class语句来实现,其语法格式:class 子类名(父类名):
6. 在Python中,用于释放对象资源的方法是( )。
A. __init__()
B. close()
C. __del__()
D. release()
【答案】C
【解析】__del__()执行一些释放资源的操作。
[归纳小结]
学科网(北京)股份有限公司
$$