写在前面:
本系列文章收录:CAU计算机类公选课《Python语言程序设计》的课堂讲义
课程时间为:2022~2023学年秋季
供各位小白参考~
第七章:面向对象程序设计
面向对象的三个特性:封装性、继承性、多态性
1.类和对象
类:用来描述相同的属性和方法的对象集合。它定义了集合中每个对象所共有的属性和方法。
比如:学生类。
对象是类的实例。
在Python中使用class关键字定义类。
对象是某个具体的实物。对象拥有自己的特征和行为。
类和对象之间关系:类是对象的类型,对象是类的实例。用类来创建(实例化)一个对象。
在程序开发中,先有类,再有对象。
2.类的定义和实例化
类是一个数据结构,类定义数据类型的属性和行为。
(1)类的定义
定义类的语法结构:
class 类名:
类的实体
类名通常以大写字母开头的单词。
类名必须为有效地标识符。
类的实体由缩进的语句块组成。
类的实体是由成员属性和成员方法组成。
【示例】类的定义示例。
class Student:
name = '吴一清'
def study(self):
print('我正在积极的学习防疫知识。')
(2)类的实例化
类是抽象的,如果要使用类定义的功能,就必须实例化类,即创建类的对象。
创建实例对象以后,可以使用“.”来调用其成员。
语法结构:
对象 = 类名()
调用的形式:对象.成员
【示例】类的创建于实例化。
class Student:
name = '吴一清'
def study(self):
print('我正在积极的学习防疫知识。')
obj = Student()
print(obj.name)
obj.study()
运行结果:
吴一清
我正在积极的学习防疫知识。
3.实例与类的对象属性
类的数据成员是在类中定义的成员变量(域),用来存储描述类的特征的值,称为属性。
属性既可以被该类中定义的方法访问,也可以通过类对象或实例对象进行访问。
(1)实例对象的属性
实例对象的属性,也称为实例对象变量,是指通过“self.变量名”定义属性。
实例对象变量在类的内部通过self访问,在外部通过对象实例访问。
在内部:self.变量名 = 初始值
在外部:对象名.变量名 = 初始值
实例对象属性,一般在__init__()方法中初始化。
【示例】实例对象属性应用。
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
def say_hello(self,song):
print(f"我叫{self.name},今年{self.age}岁,会唱{song}")
obj = Student('木子',18)
obj.say_hello('朋友')
运行结果;
我叫木子,今年18岁,会唱朋友
(2)类对象属性:
Python允许声明属于类对象本身的变量,即类对象属性。
对象属性一般在类体中,通过如下形式初始化:
类变量名 = 初始值
在其类定义的方法中或者外部代码中,通过类名访问。语法形式:
类名.类变量名 = 值 # 写入
类名.类变量名 # 读取
【示例】类对象属性的应用。
class Student:
count = 0
name = '初心'
Student.count += 1
print(Student.count)
print(Student.name)
运行结果:
1
初心
(3)类对象属性于实例对象属性的区别
1)所属的对象不同:类对象属性属于类对象本身,可以由类的所有实例共享,在内存中存在在一个副本;实例对象属性则属于类的某个特定实例。
如果存在同名的类对象属性和实例对象属性,则两者相互独立,互不影响。
2)定义的位置和方法不同:
类对象属性是在类中所有成员方法外部以“类名.属性名”形式定义的;
实例对象属性则是在构造方法或其他实例方法中以“self.属性名”形式访问。
3)访问的方法不同:
类对象属性是通过类对象以“类名.属性名”形式访问;
实例对象属性是通过类实例以“对象名.属性名”形式访问。
4.成员属性和成员方法
封装就是把客观实物抽象,并封装成对象,即将数据成员、属性、方法和事件等集合在一个整体内。
通过访问控制可以隐藏内部成员,但只允许可信的对象访问或者操作自己的那部分数据或方法。
封装优势:保证了对象的独立性,可以防止外部程序破坏对象内部的数据,同时便于程序的维护和修改。
(1)成员属性
成员属性根据访问限制,可以分为私有属性和公有属性。
通常约定以两个下划线开头,但是不以两个下划线结尾属性称为私有(private)的,其他为公有的。不能直接访问私有属性,但可以在方法内访问。
【示例】私有属性和公有属性的定义和访问。
class Custom(object):
def __init__(self,name,money):
self.name = name
self.__money = money
c = Custom('Tom',20)
print(c.name)
print(c.__money)
运行结果:
Tom
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/pythonProject/main.py", line 8, in
print(c.__money)
AttributeError: 'Custom' object has no attribute '__money'
上述例子中,name是普通属性,__money属性是私有属性。
可以通过一对包含get()和set()方法来供外部调用。
【示例】私有成员的访问。
class Custom(object):
def __init__(self,name):
self.name = name
def get_money(self):
return self.__money
def set_money(self,money):
if money > 0:
self.__money =money
else:
self.__money = money
print('参数错误')
c = Custom('Tom')
print(c.name)
c.name = 'Berry'
print(c.name)
c.set_money(-100)
c.set_money(100)
print(c.get_money())
运行结果:
Tom
Berry
参数错误
100
说明:
非私有属性可以在类的外部访问和修改。
私有属性只能通过包含set()方法来修改。
外部访问可以通过get()方法实现。
(2)成员方法
类方法的定义和普通的函数一致的。
一般情况下,类的方法的第一个参数一般为self,这种方法称之为对象实例方法。
成员方法的声明格式:
def 方法名(self,[形参列表]):
函数体
注意:虽然类方法的第一个参数为self,但调用时,用户不需要也不能给该参数传值。事实上,Python自动把对象实例传递给该参数。
对象实例方法的调用:
对象.方法名([参数列表])
类的方法和函数的区别:
(1)函数实现的是某个独立的功能,而类的方法是实现类中的一个行为,是类的一部分。
(2)类的方法必须有一个额外的第一个参数名称,按照惯例它的名称为self。Self代表的是类的实例,代表当前对象的地址(引用),且self.calss指向类。
【示例】类方法的的应用。
class Student(object):
def __init__(self,name,age):
self.name = name
self.age = age
def print_tell(self):
print('%s:%d'%(self.name,self.age))
stu_1 = Student('初心',18)
stu_1.print_tell()
运行结果:
初心:18
(3)构造方法和析构方法
构造方法是创建对象的过程中被调用的第一个方法,通常用于初始化对象需要的资源。
在定义构造方法时,需要在方法名的两侧加两个下划线,构造方法名为init。完整的构造方法为__init__()。
__init__()是一个特殊的方法,属于类的专有方法,称为类的构造函数或初始化方法。
__init__()方法的作用:初始化已实例化后的对象。
【示例】__init__()方法的应用。
class Studnet():
def __init__(self,name,sex):
self.name = name
self.sex = sex
print(self.__class__) # 验证初始化是否被执行
def showInfo(self,country):
print(f'我是{self.name},性别为{self.sex},来自{country}')
obj = Studnet('辛里美','女')
obj.showInfo('中国')
运行结果:
我是辛里美,性别为女,来自中国
5.类的继承
在面向对象程序设计中,被继承的类称为父类(基类),新的类被称为子类(派生类)。
继承功能:不仅可以实现代码的复用,而且可以通过继承来理顺类之间的关系。
语法结构:
class ClassName(baseclasslist):
statement
声明派生类时,必须在其构造函数中调用基类的构造方法。
调用格式:
基类.__init__(self,参数列表)
super().__init__(参数列表)
【示例】创建基类Animal,包含两个数据成员,name和age;创建派生类Dog,包含一个数据成员color。
class Animal(object):
def __init__(self,name,age):
self.name = name
self.age = age
def eat(self,food):
print(f'我是{self.name},{self.age}岁了,爱吃{food}')
class Dog(Animal):
def __init__(self,name,age,color):
Animal.__init__(self,name,age)
self.color = color
def eat(self,food):
Animal.eat(self,food)
print(f'我是{self.name},颜色是{self.color},爱吃{food}')
lala = Animal('拉普拉多',3)
lala.eat('鱼罐头')
jimao = Dog('金毛',2,'金黄')
jimao.eat('牛肉罐头')
运行结果:
我是拉普拉多,3岁了,爱吃鱼罐头
我是金毛,2岁了,爱吃牛肉罐头
我是金毛,颜色是金黄,爱吃牛肉罐头