8.1、类的简介
面向对象编程是最有效的软甲编程方法之一。在面向对象编程中,你编写的表示现实世界的事物和情景的类,并基于这些类来创建对象。Python 的类提供了面向对象编程的所有标准特性:类继承机制允许多个基类,派生类可以覆盖它基类的任何方法,一个方法可以调用基类中相同名称的的方法。对象可以包含任意数量和类型的数据。和模块一样,类也拥有 Python 天然的动态特性:它们在运行时创建,可以在创建后修改。于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。使用面向对象编程可模拟现实情景。根据类来创建对象被称为实例化,这让你能够使用类的实例。
8.2、定义类和使用类
最简单的类定义如下:
class ClassName:
<statement-1>
.
.
.
< statement - N >
8.2.1、定义类
示例如下:
class Student():
"""模拟学生的基本信息"""
def __init__(self,name,age,sex):
"""
初始化属性name,age和sex
:param name: 学生姓名
:param age: 学生年龄
:param sex: 学生性别
"""
self.name = name
self.age = age
self.sex = sex
def study(self):
"""
学生学习的方法
:return:
"""
print(self.name + ':学习感觉很好,每天进步一点点')
def eat(self):
"""学生吃饭的方法"""
print(self.name + ":今天已按时吃饭")
解析 init()方法:
类中的函数称之为方法,init()方法是一个特殊的方法,每当Student类创建新的实例时,Python就会自动调用它,在这个方法的名称中,开头和结尾各有两个下划线,这是一种约定,主要是避免默认方法和普通方法名称发生冲突。
上述例子中给init()方法传递四个形参:self、name、age、sex。在这个方法的定义中,形参 self 必不可少,还必须位于其他形参的前面。
为什么必须在方法定义中包含self呢?那是因为调用__init__()方法来创建Student实例时,将自动传入实参self。每个与类相关的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
我们创建Student实例时候,Python将调用Student类的方法__init__()。我们通过实参向Student()传递名字、年龄和性别;self会自动传递,因此我们不需要传递它。每当我们实例Student类时,都需要给最后三个形参(name,age,sex)提供值。
self.name = name, self.age = age,self.sex = sex定义的三个变量都有前缀self。以self为前缀的变量都可供类中的所有的方法使用,我们还可以通过类的任何实例来访问这些变量。 self.name = name 获取存储在形参name中的值,并将其存储到变量name中,然后后该变量被关联到前面创建的实例。
8.2.2、实例对象
可将类视为有关如何创建实例的说明。例对象的有效方法名称依赖于其所属的类。 根据定义,一个类中所有是函数对象的属性都是定义了其实例的相应方法。
- 访问属性
要访问实例的属性,可使用句点表示法。
# 实例化对象
stu = Student('刘诗诗','26','女')
# 通过对象名访问属性
print(stu.name)
- 调用方法
# 通过对象名调用Student类中的方法
stu.study()
- 创建多个实例
可按需求根据类创建任意数量的实例。
# 实例化多个对象
stu = Student('刘诗诗','26','女')
stu1 = Student('王刚','38','男')
stu2 = Student('张起灵','128','男')
stu3 = Student('无邪','20','男')
上述实例中,一共创建了4个学生信息
8.3、运用类和实例对象
我们可以用类来模拟现实世界中很多场景。编写好之后,大部分时间将用在根据类创建实例上,可直接修改实例的属性,也可编写方法以特定的方式进行修改。
8.3.1、编写一个类
模拟编写一个汽车类,存储了有关汽车的信息
class Car():
"""模拟汽车 -> make :制作 ;model:模型;year:年份"""
def __init__(self,make,model,year):
"""初始化描述汽车的属性"""
self.make = make # 制作
self.model = model # 模型
self.year = year # 年份
def get_car_information(self):
"""返回一些描述汽车的信息"""
mesg_name = '生产于:'+str(self.year)+'年 --> 类型:'+self.make+' --> 型号:'+self.model
return mesg_name
def print_info(self):
return print(self.get_car_information())
my_new_car = Car('四轮子','A4','2022')
my_new_car.print_info()
8.3.1、给属性设置默认值
类中的每个属性都必须有初始值,哪怕这个值是0或者空字符串。在有些情况下,如设置默认值时,在方法__init__()内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
我们给上述案例添加一个功能,查看汽车公里数
class Car():
"""模拟汽车 -> make :制作 ;model:模型;year:年份"""
def __init__(self,make,model,year):
"""初始化描述汽车的属性"""
self.make = make # 制作
self.model = model # 模型
self.year = year # 年份
self.odometer = 0
def get_read_odometer(self):
"""获取汽车的里程信息"""
print("此款"+self.make+self.model+
'型车已行驶'+str(self.odometer) + '公里')
def get_car_information(self):
"""返回一些描述汽车的信息"""
mesg_name = '生产于:'+str(self.year)+'年 --> 类型:'+self.make+' --> 型号:'+self.model
return mesg_name
def print_info(self):
return print(self.get_car_information())
my_new_car = Car('四轮子','A4','2022')
my_new_car.print_info()
my_new_car.get_read_odometer()
运行结果:
生产于:2022年 --> 类型:四轮子 --> 型号:A4
此款四轮子A4型车已行驶0公里
8.3.2、修改属性的值
修改属性值的方式有3种:直接通过实例进行修改;通过方法进行设置;通过方法进行递增(增加特定的值)
- 直接修改属性值
用实例对象名直接访问属性,然后赋值。
my_new_car = Car('四轮子','A4','2022') # 实例化对象
my_new_car.print_info() # 获取汽车基本信息
my_new_car.odometer = 90 # 直接给里程表(odometer)赋值
my_new_car.get_read_odometer() # 获取里程表方法
- 通过方法进行修改属性的值
通过方法修改,是最合乎情景的方式
class Car():
"""模拟汽车 -> make :制作 ;model:模型;year:年份"""
def __init__(self,make,model,year):
"""初始化描述汽车的属性"""
self.make = make # 制作
self.model = model # 模型
self.year = year # 年份
self.odometer = 0
def get_read_odometer(self):
"""获取汽车的里程信息"""
print("此款"+self.make+self.model+
'型车已行驶'+str(self.odometer) + '公里')
def update_orometer(self,mileage):
"""将里程表读数设置为指定的值"""
self.odometer = mileage
def get_car_information(self):
"""返回一些描述汽车的信息"""
mesg_name = '生产于:'+str(self.year)+'年 --> 类型:'+self.make+' --> 型号:'+self.model
return mesg_name
def print_info(self):
"""打印汽车信息方法"""
return print(self.get_car_information())
my_new_car = Car('四轮子','A4','2022')
my_new_car.print_info()
# my_new_car.odometer = 90
my_new_car.update_orometer(80) # 调用此方法为里程表设置值
my_new_car.get_read_odometer()
代码解析:def update_orometer(self,mileage):这个方法接收一个里程值,将这个值存到self.odometer中。之后调用此方法,并传入里程数。如下运行结果:
防止往回调里程表,update_odometer()进行优化。
def update_orometer(self,mileage):
"""
将里程表读数设置为指定的值
禁止将里程表数让回调
"""
if mileage >= self.odometer:
self.odometer = mileage
else:
print("您的操作无效")
测试:
my_new_car = Car('四轮子','A4','2022')
my_new_car.print_info()
# my_new_car.odometer = 90
my_new_car.update_orometer(70) # 调用此方法为里程表设置值
my_new_car.update_orometer(30) #往回调里程表数字
my_new_car.get_read_odometer()
运行结果:
3. 通过方法对属性值进行递增
有时需要将属性值递增特定的量,而不是将其设置为全新的值。
假设我们购买的是二手车,从购买到登记期间增加了100公里的里程。
def update_orometer(self,mileage):
"""
将里程表读数设置为指定的值
禁止将里程表数让回调
"""
if mileage >= self.odometer:
self.odometer = mileage
else:
print("您的操作无效")
def increment_odometer(self,miles):
"""将里程表读数增加指定的量"""
self.odometer += miles
调用方法:
my_new_car = Car('四轮子','A4','2022')
my_new_car.print_info()
# my_new_car.odometer = 90
my_new_car.update_orometer(100) # 调用此方法为里程表设置值
my_new_car.get_read_odometer()
my_new_car.increment_odometer(50)
my_new_car.get_read_odometer()
运行结果:
注意: 你可以使用类似于上面的方法来控制用户修改属性值(如里程表读数)的方式,但能够访问程序的人可以通过直接访问属性来将里程表改为任何值。