一、面向对象的基本概念
常用的编程方式有面向过程(C,Fortran)和面向对象(C++,Java,Python)两种
拿做菜举例,面向过程是将做菜的过程,按步骤逐步做好菜。面向对象则是直接将菜名作为指令发给做菜机器人,由机器人完成。
二、类(class)
2.1 类的基本概念
类是对具有相同属性和方法的一组对象的描述或定义。
类的创建方法:
示例说明
class Car(): #创建一个类,通常按照规范,类的名称首字母需大写以与其他变量区分
def __init__(self,make,model,year): #当类Car被创建一个对象时,Python会自动运行该方法。
#下划线是一种约定,避免Python默认的方法与普通方法名称冲突
#self必不可少,且必须位于其他形参的前面
self.make=make #可通过对象访问的变量称为属性
self.model=model#将变量保存为self的属性后,函数外也可引用该属性,否则局部变量只能在函数内使用
self.year=year
def detection(self):
duration=2022-self.year
price=30-2*duration
long_name="你的"+self.make+self.model\
+"到目前已经行驶了"+str(duration)\
+"年,"+"目前价值"+str(price)+"万"
return long_name
my_car=Car("Audi","A4",2012)#定义一个类对象
print(my_car.year)#调用对象的year属性
print(my_car.detection())
# 调用方式和变量的方法调用方式类似
# 例如 a= [1,2,3] a.append(4),其中append在定义时也会写作__append__以与自定义的方法区分
--输出
2012
你的AudiA4到目前已经行驶了10年,目前价值10万
2.2 类的属性管理
可通过对象访问的变量称为属性。
可以通过self.属性=默认值
的方式为属性指定默认值
也可以通过对象的名称.属性=修改值
修改属性的值
class Car():
def __init__(self,make,model,year):#若变量无需传参,可以不写在()内
self.make=make #可通过对象访问的变量称为属性
self.model=model
self.year=year
self.this_year=2022#将属性this_year的默认值设为2022
def detection(self):
duration=self.this_year-self.year#调用属性this_year
price=30-2*duration
long_name="你的"+self.make+self.model\
+"到目前已经行驶了"+str(duration)\
+"年,"+"目前价值"+str(price)+"万"
return long_name
my_car=Car("Audi","A4",2012)
my_car.this_year=2023#修改属性的值
print(my_car.detection())
--输出
你的AudiA4到目前已经行驶了11年,目前价值8万
也可以通过函数对属性值进行修改
#在以上代码基础上增加函数mod_this_year
def mod_this_year(self,newyear):
self.this_year=newyear
#调用函数
my_car=Car("Audi","A4",2012)
my_car.mod_this_year(2023)
print(my_car.detection())
--输出
你的AudiA4到目前已经行驶了11年,目前价值8万#年份已被改为2023
2.3 导入类
Python可以将类存储在模块中,然后在主程序中导入所需要的模块
1.导入单个类:from 模块名 import 类名
打开指定模块名文件并导入类在本文件中。
在一个模块中可以同时存储多个类
from car import Car
from car import ElectricCar
2.从一个模块中导入多个类:from 模块名 import 类名1,类名2
from car import Car,ElectricCar
3.导入整个模块:import 模块名
导入整个模块时,在使用过程中需要以句点的形式访问模块中的类,例如模块a中有类A1,A2,A3
,而在主程序中使用类时为a.A1,a.A2,a.A3
import car
my_car=Car("Audi","A4",2012)
print(my_car.detection())
--报错
my_car=Car("Audi","A4",2012)
NameError: name 'Car' is not defined. Did you mean: 'car'?
#需在调用Car类时带上模块名称
import car
my_car=car.Car("Audi","A4",2012)
print(my_car.detection())
--输出
你的AudiA4到目前已经行驶了10年,目前价值10万
1,2两种方式相当于将Car和ElectricCar类中的代码直接导入,而方法3只是提供了进入car文件的入口,因此调用类时需要带上模块名称。
4.导入模块中的所有类:from 模块名 import *
from car import *
第4种方法虽然简便,但会导致模块中所有的类都导入程序中,导致程序读取内容增多,增加运行负担。因此只有当模块中类较少或全部均需导入时,才会采用第4种方法
三、继承
3.1 概念
当编写的类是另一个线程类的特殊版本,可使用继承。
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法。原来的类称为父类,而新的类称为子类。
通过super().__init__()
对子类父类进行连接,使子类继承父类所有的属性和方法
3.2 实例
- 子类的初始化
class Car():
def __init__(self,make,model,year):
self.make=make
self.model=model
self.year=year
self.this_year=2022
def detection(self):
duration=self.this_year-self.year
price=30-2*duration
long_name="你的"+self.make+self.model\
+"到目前已经行驶了"+str(duration)\
+"年,"+"目前价值"+str(price)+"万"
return long_name
class ElectricCar(Car): #父类必须写在子类前面
def __init__(self,make,model,year):
#super函数将父类和子类关联起来,让python调用ElectricCar的父类的方法__init__()
super().__init__(make,model,year)#父类为超类,super因此得名
#以上两行代码,就可以使子类继承父类所有的属性和方法
my_tesla=ElectricCar("Tesla","AC",2019)
print(my_tesla.detection())
- 子类的新方法定义
父类定义的方法,子类都可以使用。
当子类创建新方法时:
①子类可直接创建全新的方法。在子类中定义的方法,只能同子类创建的对象中使用该方法,不能在通过父类创建的对象中使用。
②若需要在子类中对方法进行修改时,无需修改方法名称,直接在子类中进行重写即可。
在子类创建的方法名称如果和父类相同,通过子类创建的对象会使用子类的该方法,通过父类创建的对象会使用父类的该方法
#假设父类Car已创建
class ElectricCar(Car):
def __init__(self,make,model,year):
super().__init__(make,model,year)
def battery(self,capacity):#定义子类的全新方法
self.capacity_num=capacity
print("您选择的电池容量是:}kwh".format(self.capacity_num))
def detection(self): #重写父类方法
duration = self.this_year - self.year
price = 30 - duration- (500/self.capacity_num)
long_name = "新方法:你的" + self.make + self.model +"到目前已经行驶了" + str(duration) + "年," + "目前价值" + str(round(price,1)) + "万"
return long_name
my_tesla=ElectricCar("Tesla","AC",2019)#声明子类对象
capacity=eval(input('请输入电池容量:'))
my_tesla.battery(capacity)#调用子类方法
print(my_tesla.detection())#调用子类重写的方法
my_car=Car("Audi","A4",2012)#声明父类对象
print(my_car.detection())#调用父类的方法
--输出
请输入电池容量:55
您选择的电池容量是:55kwh
新方法:你的TeslaAC到目前已经行驶了3年,目前价值17.9万#子类重写的方法输出
你的AudiA4到目前已经行驶了10年,目前价值10万#父类则调用的是旧方法