面向对象是一种抽象化的编程思想,很多编程语言都有一种的思想。 例如:洗衣服 思考:几种途径可以完成洗衣服? 答: 手洗 和 机洗。 对比发现机洗更简单。 面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。
在面向对象编程过程中,有两个重要组成部分:类和对象。 类和对象的关系:用类去创建一个对象。
类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。 ·0·特征即是属性(变量) ·0·行为即是方法(函数) 类比如实制造洗衣机时要用到的图纸,也就是说类是用来创建对象。
对象是类创建出来的真实存在的事物,例如:洗衣机。 注意:开发中,先有类,再有对象
定义类 语法: Class 类名(): 代码 …… 注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯。
class Washer(): def wash(self): print('能洗衣服') # 2.创建对象 # 对象名 = 类名() haier = Washer() # 3.验证成果 # 打印haier对象 print(haier) # 使用wash功能 -- 实例方法/对象方法 -- 对象名.Wash() haier.wash()self指的是调用该函数的对象 谁调用了该函数self指的就是哪个对象 打印self的地址和实例化对象的地址会发现他们两个一样
一个类可以创建多个对象; 多个对象都调用函数的时候,self地址不相同
属性即是特征,比如:洗衣机的宽度,高度,重量…… 对象属性既可以在类外面添加和获取,也能在类里面添加和获取。
语法: 对象名.属性名 = 值 实例: haier1.height = 500
语法: 对象名.属性名 实例: print(f’haier1洗衣机的高度是{haier.height}’)
语法: self.属性名
class Washer(): def wash(self): print('洗衣服') # 获取对象属性 def print_info(self): # self.属性名 # print(self.height) print(f'洗衣机的高度是{self.height}') haier1 = Washer() # 添加属性 haier1.height = 400 # 对象调用方法 haier1.print_info()在python中,xx()的函数叫做魔法方法,指的是具有特殊功能的函数
__init_()方法的作用:初始化对象。
class Washer(): def wash(self): print('洗衣服') # 获取对象属性 def print_info(self): # self.属性名 # print(self.height) print(f'洗衣机的高度是{self.height}') haier1 = Washer() # 添加属性 haier1.height = 400 # 对象调用方法 haier1.print_info()__init__()方法,在创建一个对象时默认被调用,不需要手动调用 __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。 4.1.2 带参数的__init__() 思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢? 答:传参数
class Washer(): # 定义_init_,添加实例属性 def __init__(self, width, height): # 添加实例属性 self.width = width self.height = height def print_info(self): # 类里面调用实例属性 print(f'洗衣机的宽度是{self.width},高度是{self.height}') haier1 = Washer(10, 20) haier1.print_info() haier1 = Washer(30, 40) haier1.print_info()当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__()方法,那么就会打印从在这个方法中return的数据。
class Washer(): def __init__(self, width, height): self.width = width self.height = height def __str__(self): return '这是海尔洗衣机的说明书' haier1 = Washer(10, 20) print(haier1)当删除对象时,python解释器也会默认调用__del__()方法。
class Washer(): def __init__(self, weight, height): self.weight = weight self.height = height def __del__(self): print(f'{self}对象已经被删除') haier1 = Washer(10, 20) del haier11需求 需求主线:
被烤的时间和对应的地瓜状态: 0-3分钟:生的 3-5分钟:半生不熟 5-8分钟:熟的 超过8分钟:烤糊了2.添加的调料: 用户可以按自己的意愿添加调料
①步骤分析: 需求涉及一个事物: 地瓜,故案例涉及一个类:地瓜类。
②定义类 ·0· 地瓜的属性 被烤的时间 地瓜的状态 添加的调料 ·0· 地瓜的方法 被烤 =用户根据意愿设定每次烤地瓜的时间 =判断地瓜被烤的总时间是在哪个区间,修改地瓜状态 ·0·添加调料 =用户根据意愿设定添加的调料 =将用户添加的调料存储 ·0·显示对象信息
# 1.定义类:初始化属性,被烤和添加调料的方法,显示对象信息的str class SweetPotato(): def __init__(self): # 被烤的时间 self.cook_time = 0 # 地瓜的状态 self.cook_state = '生的' # 调料列表 self.condiments = [] def cook(self, time): """烤地瓜的方法""" self.cook_time += time if 0 <= self.cook_time < 3: self.cook_state = '生的' elif 3 <= self.cook_time < 5: self.cook_state = '半生不熟' elif 5 <= self.cook_time < 8: self.cook_state = '熟了' elif self.cook_time >= 8: self.cook_state = '烤糊了' def __str__(self): return f'这个地瓜的烤制时间为{self.cook_time},状态是{self.cook_state},添加的调料有{self.condiments}' def add_condiments(self, condiment): """添加调料""" self.condiments.append(condiment) # 2.创建对象并调用对应的实例方法 digua1 = SweetPotato() print(digua1) digua1.cook(2) digua1.add_condiments('辣椒面') print(digua1) digua1.cook(2) print(digua1)1需求: 将小于房子 剩余面积的家具摆放到房子中
2 需求分析 需求涉及到两个事物: 房子 和 家具, 故被案例涉及两个类:房子类 和 家具类。
① 定义类 · 0 · 房子类 @实例属性 =房子地理位置 =房子占地面积 =房子剩余面积 =房子内家具列表 @实例方法 =容纳家具 @显示房屋信息 · 0 · 家具类 @家具名称 @家具占地面积 ② 创建对象并调用相关方法
class Furniture(): def __init__(self, name, area): self.name = name self.area = area class Home(): def __init__(self, address, area): # 地理位置: self.address = address # 房屋面积: self.area = area # 剩余面积 self.free_area =area # 家具列表 self.furniture = [] def __str__(self): return f'房子坐落于{self.address}, 占地面积{self.area}, 剩余面积{self.free_area}, 家具有{self.furniture}' def add_furniture(self, item): """容纳家具""" if self.free_area >= item.area: self.furniture.append(item.name) # 家具搬入后,房屋剩余面积 = 之前剩余面积 - 该家具面积 self.free_area -= item.area else: print('家具太大,剩余面积不足,无法容纳') bed = Furniture('双人床', 6) sofa = Furniture('沙发', 10) # 房子1: 北京, 1000 jia1 = Home('北京', 1000) print(jia1) jia1.add_furniture(bed) print(jia1) jia1.add_furniture(bed) print(jia1)·面向对象重要组成部分
生活中的继承,一般指的是子女继承父辈的财产。
class 类名(object): 代码Python面向对象的继承指的是多个类之间的所属短息,即子类默认继承父类的所有属性和方法,具体如下:
# 父类A class A(object): def __init__(self): self.num = 1 def info_print(self): print(self.num) # 子类B class B(A): pass result = B() result.info_print()在python中,所有类默认继承object类,obj类是顶级类或基类;其他子类叫做派生类。
魔法方法__mro__:显示出一个类的继承顺序: print(Prentice.__mro__)
如果在调用父类的同名方法和属性的时候,没有填入self表示接受则会产生报错。
缺少位置参数:在调用make_cake函数的时候,没有代表调用对象的参数,需要填入self来表示对象的形参。
父类再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在init初始化位置,所以需要再次调用init。
子类函数再次调用初始化的原因:如果不加自己的初始化,kongfu的属性值是上一次调用的init内的kongfu属性值
注意:使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用
在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。 设置私有权限的方法:在属性名和方法名 前面 加上两个下划线_。
def __init__(self): self.kongfu = '正派煎饼果子方法' self.__money = 1000 def __info_print(self): print('这是私有方法') print(tudi.__money) super().make_cake()
在python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。(工作习惯)
def get_money(self): return self.__money # 修改私有属性 def set_money(self): self.__money = 500 print(tudi.get_money()) #1000 tudi.set_money() print(tudi.get_money()) #500·0· 继承的特点 =子类默认拥有父亲的所有属性和方法 =子类重写父类同名方法和属性 =子类调用父类同名方法和属性
·0· super()方法快速调用父类方法
·0· 私有权限 =不能继承给子类的属性和方法需要添加私有权限 =语法
class 类名(): # 私有属性 __属性名 = 值 # 私有方法 def __函数名(self): 代码学习目标:
面向对象三大特性类属性和实例属性类方法和静态方法多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)
·0· 定义:多态十一中使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
·0· 好处:调用灵活,有了堕胎,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化。
·0· 实现步骤: = 定义父类,并提供父类方法 = 定义子类,并重写父类方法 = 传递子类对象给调用者,可以看到不用子类执行效果不同
class Dog(object): def work(self): pass class ArmyDog(Dog): def work(self): print('撕咬敌人') class DrugDog(Dog): def work(self): print('追查毒品') class Person(object): def work_with_dog(self,dog): dog.work() ad = ArmyDog() dd = DrugDog() person = Person() person.work_with_dog(ad) #撕咬敌人 person.work_with_dog(dd) #追查毒品设置和访问类属性 ·0· 类属性就是类对象所拥有的属性,它被 该类的所有实例对象所共有。 ·0· 类属性可以使用类对象或实例对象访问。 类属性的优点 = 记录的某项属性 始终保持一致时,则定义类属性。 = 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有,仅占用一份内存,更加节省内存空间。
类属性只能通过对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
# 修改类属性 类.类属性 = 值 Dog.tooth = 20 print(ad.tooth) # 20 print(dd.tooth) # 20 print(Dog.tooth) # 20 # 修改实例属性 实例.类属性 = 值 ad.tooth = 100 print(ad.tooth) # 100 print(dd.tooth) # 20 print(Dog.tooth) # 20a) 类方法特点 = 需要用装饰器@classmethod 来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。
b) 类方法使用场景 = 类方法中 需要使用类对象(如访问私有类属性等)时,定义类方法 = 类方法一般和类属性配合使用
# 1. 定义类:私有类属性, 类方法获取这个私有类属性 class Dog(object): __tooth = 10 # 定义类方法 @classmethod def get_tooth(cls): #cls 代表了Dog类 return cls.__tooth # 2.创建对象,调用类方法 wangcai = Dog() result = wangcai.get_tooth() print(result)a) 静态方法特点 ·0· 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。 ·0· 静态方法也能够通过 实例对象 和 类对象 去访问。
b) 静态方法使用场景 ·0· 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性,类方法,创建实例等)时,定义静态方法。 ·0· 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗。
# 1.定义类,定义静态方法 class Dog(object): @staticmethod def info_print(): print('这是一个静态方法') # 2.创建对象 wangcai = Dog() # 3.调用静态方法: 类 和 对象 wangcai.info_print() # 这是一个静态方法 Dog.info_print() # 这是一个静态方法·0· 面向对象三大特性 =1=封装 =2=继承 =3=多态
·0· 类属性 =归属于类对象的属性,所有对象共有的属性
·0· 实例属性
·0· 类方法
@classmethod def xx(): 代码·0· 静态方法
@staticmethod def xx(): 代码当检测到一个错误时,解释器就无法继续运行了,反而出现了一些错误的提示,这就是所谓的“异常”。
@语法
# 需求:尝试打开test.txt(r) ,如果文件不存在,只写方式打开w """ try: 可能发生错误的代码 except: 发生错误的时候执行的代码 """ try: f = open('test.txt', 'r') except: f = open('test.txt', 'w')@ 语法
""" try: 可能发生错误的代码 except 异常类型: 如果捕获到该异常类型执行的代码 """ try: print(num) except NameError: print('有错误') # 一般try下方只放一行尝试执行的代码。当捕获多个异常时,可以把要捕获的异常类型的名字,放到except后,并使用元组的方式进行书写。
try: print(1/0) except (NameError, ZeroDivisionError): print('有错误')Exception是所有程序异常类的父类。
try: print(num) except Exception as result: print(result) # name 'num' is not definedelse表示的是如果没有异常要执行的代码
try: print(1) except Exception as result: print(result) else: print('无异常')finally表示的是无论是否异常都要执行的代码。
体验异常传送
需求:
尝试只读方式打开test.txt文件,如果文件存在则读取文件内容,文件不存在则提示用户即可。读取内容要求: 尝试循环读取内容,读取过程中如果检测到用户以外终止程序,则except捕获异常并提示用户。 # 需求1: 尝试只读打开test.txt 文件存在遁去内容,不存在提示用户 # 需求2: 读取内容:循环读取,当无内容的时候退出循环,如果用户意外终止,提示用户已经被意外终止 import time try: f = open('test.txt') # 尝试循环读取内容 try: while True: con = f.readline() # 如果读取完成退出循环 if len(con) == 0: break time.sleep(3) print(con) except: # 在命令提示符中如果按下ctrl+c结束终止的键 print('程序被意外终止') except: print('该文件不存在')在python中,抛出自定义异常的语法为raise异常类对象。 需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则报错,即抛出自定义异常,并捕获该异常)。
·0· 异常语法
try: 可能发生异常的代码 except: 如果出现异常执行的代码 else: 没有异常执行的代码 finally: 无论是否异常都要执行的代码·0· 捕获异常
except 异常类型: 代码 except 异常类型 as xx: 代码·0· 自定义异常
class 异常类类名(Exception): 代码 # 设置抛出异常的描述信息 def __str__(self): return ……·0· 抛出异常 raise 异常类名()
·0· 捕获异常 except Exception……