学习网址
学习网址:
- https://python666.cn/cls/lesson/48/
- https://python666.cn/cls/lesson/49/
- https://python666.cn/cls/lesson/50/
- https://python666.cn/cls/lesson/51/
面向对象基本概念
类的概念
- 按照功能需求的顺序来设计程序。这种被称为“面向过程”的编程。
- 把数据和对数据的操作用一种叫做“对象”的东西包裹起来。被称为“面向对象”的编程。这种方法更适合较大型的程序开发。
类是一种抽象的类型,而对象是这种类型的实例。
面向对象编程最主要的两个概念就是:类(class)和对象(object)
举个现实的例子:
“笔”作为一个抽象的概念,可以被看成是一个类。而一支实实在在的笔,则是“笔”这种类型的对象。
类的三个最重要的概念
- 封装
- 继承
- 多态
# 封装就是将代码全部集合到类中,通过类实例名.方法去访问相关代码
# 继承就是将不同类的相同的功能给聚合在一个类中,定义类时区继承这个类就可以不用再写这些相同的功能
# 多态就是在父类中定义的属性或方法被子类继承之后,在不同情况下表现出不同的行为。就是同一个方法名,针对不同的对象产生不同的效果。
类的基本组成
一个类可以有属于它的函数,这种函数被称为类的“方法”。
一个类/对象可以有属于它的变量,这种变量被称作“域”。
域根据所属不同,又分别被称作“类变量”和“实例变量”。
域和方法被合称为**
类的属性
**。例子:
一个笔有书写的功能,所以“书写”就是笔这个类的一种方法。每支笔有自己的颜色,“颜色”就是某支笔的域,也是这支笔的实例变量。
类的基本操作
创建类
class MyClass:
pass
类创建语句:
关键字class加上类名用来创建一个类 class class_name: pass # 类内部的语法块
创建类实例
mc = MyClass()
print (mc)
类名加圆括号()的形式可以创建一个类的实例,也就是被称作对象的东西。
# 把这个对象赋值给变量mc。于是,mc现在就是一个MyClass类的对象。
# 输出结果:
<__main__.MyClass instance at 0x7fd1c8d01200>
# 解释:mc是__main__模块中MyClass来的一个实例(instance),后面的一串十六进制的数字是这个对象的内存地址。
创建类的域和类方法
class MyClass:
name = 'Sam'
def sayHi(self):
print ('Hello %s' % self.name)
mc = MyClass()
print (mc.name)
mc.name = 'Lily'
mc.sayHi()
# 输出结果:
# Sam
# Hello Lily
给
MyClass
类增加了一个类变量name,并把它的值设为'Sam'。然后又增加了一个类方法sayHi
。调用类变量的方法是“对象.变量名”。可以得到它的值,也可以改变它的值。
'''
注意:
类方法,第一个参数必须为self。
在调用类方法的时候,通过“对象.方法名()”格式进行调用,不需要额外提供self这个参数的值。
self在类方法中的值,就是调用的这个对象本身。(即可以通过self.变量名来访问类里面的变量)
'''
类的一个简单例子
第一个例子
假设有一辆汽车,知道它的速度(60km/h),以及A、B两地的距离(100km)。要算出开着这辆车从A地到B地花费的时间。
- 面向过程的方法:
speed = 60.0
distance = 100.0
time = distance / speed
print (time)
- 面向对象的方法:
class Car:
speed = 0
def drive(self, distance):
time = distance / self.speed
print (time)
car = Car()
car.speed = 60.0
car.drive(100.0)
第二个例子
又有一辆更好的跑车,它的速度是150km/h,然后除了想从A到B,还要从B到C(距离200km)。要求分别知道这两种车在这两段路上需要多少时间。
- 面向过程的方法:
speed1 = 60.0
distance1 = 100.0
time1 = distance1 / speed1
print (time1)
distance2 = 200.0
time2 = distance2 / speed1
print (time2)
speed2 = 150.0
time3 = distance1 / speed2
print (time3)
time4 = distance2 / speed2
print (time4)
- 面向对象的方法:
class Car:
speed = 0
def drive(self, distance):
time = distance / self.speed
print (time)
car1 = Car()
car1.speed = 60.0
car1.drive(100.0)
car1.drive(200.0)
car2 = Car()
car2.speed = 150.0
car2.drive(100.0)
car2.drive(200.0)
对比两种方法:
面向过程把数据和处理数据的计算全部放在一起,当功能复杂之后,就会显得很混乱,且容易产生很多重复的代码。
面向对象,把一类数据和处理这类数据的方法封装在一个类中,让程序的结构更清晰,不同的功能之间相互独立。这样更有利于进行模块化的开发方式。
第三个例子
仍然是从A地到B地,这次除了有汽车,还有了一辆自行车!
自行车和汽车有着相同的属性:速度(speed)。还有一个相同的方法(drive),来输出行驶/骑行一段距离所花的时间。但这次要给汽车增加一个属性:每公里油耗(fuel)。而在汽车行驶一段距离的方法中,除了要输出所花的时间外,还要输出所需的油量。
# 阅读题目可以知道:(按照上面学习的知识来解答) # 要定义两个类,自行车和汽车分别写一个类, # 汽车类中有一个属性(speed)、两个方法(drive、fuel) # 自行车类中有一个属性(speed)、一个方法(drive)
解题方式:
面向过程的方法:可能需要写两个函数,然后把数据作为参数传递进去,在调用的时候要搞清应该使用哪个函数和哪些数据。
面向对象的方法:可以把相关的数据和方法封装在一起,并且可以把不同类中的相同功能整合起来。【把不同的类中所具有的相同功能给整合起来,再在其他类中单独添加不同的功能】
这就需要用到面向对象中的另一个重要概念:继承。
# 继承就是将不同类的相同的功能给聚合在一个类中,定义类时区继承这个类就可以不用再写这些相同的功能
解题过程:
要使用的方法是,创建一个叫做Vehicle的类,表示某种车,它包含了汽车和自行车所共有的东西(也就是相同的功能):速度,行驶的方法。然后让Car类和Bike类都继承这个Vehicle类,即作为它的子类。在每个子类中,可以分别添加各自独有的属性。
Vehicle类被称为基本类或超类,Car类和Bike类被成为导出类或子类。
class Vehicle:
def __init__(self, speed):
self.speed = speed
def drive(self, distance):
print ('need %f hour(s)' % (distance / self.speed))
class Bike(Vehicle):
pass
class Car(Vehicle):
def __init__(self, speed, fuel):
Vehicle.__init__(self, speed)
self.fuel = fuel
def drive(self, distance):
Vehicle.drive(self, distance)
print ('need %f fuels' % (distance * self.fuel))
b = Bike(15.0)
c = Car(80.0, 0.012)
b.drive(100.0)
c.drive(100.0)
解释一下代码:
__init__函数
会在创建一个类的对象(实例)时自动调用,用来初始化这个实例。它的参数,要在创建对象(实例)的时候提供。提供一个数值来初始化speed的值。
【就是初始化函数,每次创建一个类的实例的时候都会默认执行一次init函数,如果在定义类的时候要求传入参数,那么需要再类实例的时候传入参数】
注意:__init__是python的内置方法,类似的函数名前后是两个下英文划线。
**class定义后面的括号里表示这个类继承于哪个类。**Bike(Vehicle)就是说Bike是继承自Vehicle中的子类。Vehicle中的属性和方法,Bike都会有。
Car类中,又
重新定义了init和drive函数,这样会覆盖掉它继承自Vehicle的同名函数
。但依然可以通过Vehicle.函数名
来调用它的超类方法。以此来获得它作为Vehicle所具有的功能。注意,因为是通过类名调用方法,而不是像之前一样通过对象来调用,所以这里必须提供self的参数值。在调用超类的方法之后,又给Car增加了一个fuel属性,并且在drive中多输出一行信息。最后,分别创建一个速度为15的自行车对象,和一个速度为80、耗油量为0.012的汽车,然后让它们去行驶100的距离。