python--面向对象-文件读写-异常

一、继承

定义一个类时,需要使用另外一个类的方法或属性,就可以通过继承实现

object是Python的顶级类,创建类是会自动继承,就拥有object中的方法

  • 定义格式
复制代码
# 类的定义 
# 旧式类定义 一般在定义单个类时使用
class 类名:
    name = None
    
    def func(self):
        pass
​
# 新式类定义   一般在继承时使用
class 类名(指定需要继承的类):
    name = None
    
    def func(self):
        pass
​
​
复制代码
# 新式类定义
class A():
    name = '张三'
​
    def func(self):
        # pass 不做处理
        pass
# 旧式类
class B:
​
    age = 20
​
    def fucn(self):
        pass
​
​
print(A.name)
print(B.age)

1-1 单继承

一次继承一个类
(1)Father类有一个性别属性,默认为男,同时,Father跑步速度快;

(2)如果Son类也想要拥有这些属性和方法,该怎么做呢?

(3)执行程序,观察程序效果。

复制代码
# 单继承  只继承一个类
class Father:
​
    gender = '男'
​
    def run(self):
        print('跑步很快')
​
​
​
# 子类继承父类获取父类中属性和方法
class Son(Father):
​
    # 定义子类的属性和方法
    age = 20
​
    def play(self):
        print('玩游戏')
​
        
# 创建子类对象
s = Son()
# 使用子类对象操作父类的属性和方法以及自己的属性和方法
print(s.gender)
print(s.age)
​
s.run()
s.play()

(1)从前,有个摊煎饼的老师傅[Master],在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼(flapjack)技术;

(2)渐渐地,老师傅老了,就想着把这套技术传授给他唯一的最得意的徒弟[Apprentice];

(3)试着通过初始化、无参、定义方法与单继承来模拟程序。

复制代码
# 单继承的使用
class Master:
    name = '师父'
​
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
​
​
class Apprentice(Master):
    # 子类继承后可以不定义属性和方法,直接使用父类的方法
    pass
​
​
a = Apprentice()
​
# 子类使用父类方法
a.flapjack()

1-2 多继承

继承多个类
(1)徒弟是个爱学习的好孩子,想学习更多的摊煎饼技术;

(2)于是,在百度搜索到黑马程序员学校[School],报班来培训学习如何摊煎饼;

(3)使用多继承形式模拟程序。

复制代码
# 单继承的使用
class Master:
    name = '师父'
​
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
​
class School:
​
    name = '学校'
​
    def flapjack(self):
        print('摊肉肠煎饼')
​
​
class Apprentice(Master,School):
    # 子类继承后可以不定义属性和方法,直接使用父类的方法
​
    pass
​
​
a = Apprentice()
​
# 子类使用父类方法
a.flapjack()
​
# 查看子类的继承父类顺序
print(Apprentice.__mro__)

​

(1)可以发现老师傅[Master]、培训学校[School]都有摊煎饼方法;

(2)在徒弟对象中调用摊煎饼方法,会执行哪个父类的方法呢?

调用第一个父类的方法,print(Apprentice.__mro__) # 查看类的继承执行顺序

(3)思考:当给父类培训学校[School]新增编程方法后,子类能调用方法吗?

多继承时,父类方法都能被继承,但是如果有相同方法名,则在执行方法时,会按照print(Apprentice.__mro__)显示的顺序查找方法执行

如果想要能后执行所有父类方法,则需要将函数名字进行修改,避免函数名冲突

复制代码
# 单继承的使用
class Master:
    name = '师父'
​
    def master_flapjack(self):
        print('摊鸡蛋煎饼')
​
​
class School:
​
    name = '学校'
​
    def school_flapjack(self):
        print('摊肉肠煎饼')
​
​
class Apprentice(School,Master):
    # 子类继承后可以不定义属性和方法,直接使用父类的方法
​
    pass
​
a = Apprentice()
​
# 子类使用父类方法
a.master_flapjack()
a.school_flapjack()
​
# 查看子类的继承父类顺序
print(Apprentice.__mro__)
​

1-3 方法重写

子类中定义了和父类相同的方法,就是对父类方法的重写,在执行方法时,使用的是子类的逻辑代码
(1)徒弟非常认真学习,终于掌握了老师傅的技术;

(2)接着,自己潜心钻研出类独门配方的全新摊煎饼技术;

(3)使用方法重写对摊煎饼方法进行处理。

当对父类方法重写后,执行时只会执行子类的的方法逻辑,不会再执行父类方法中的逻辑

复制代码
# 重写父类方法  子类继承父类后定义了一个和父类相同名字的方法
​
# 单继承的使用
class Master:
    name = '师父'
​
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
​
class Apprentice(Master):
​
    # 子类中定义了自己方法,和父类方法名一样
    # 子类相当于重写了父类的方法,在执行时按照子类的逻辑执行
    def flapjack(self):
        print('摊手抓饼')
​
​
a = Apprentice()
a.flapjack()

子类重写父类方法,在调用时执行的子类的逻辑,还想调用父类方方法,需要借助super()方法实现


(1)徒弟在培训学校学习努力,不仅掌握了黑马摊煎饼配方、还创办了自己煎饼果子的品牌;[配方、品牌]

(2)配合着一起摊煎饼,做出了更加美味的煎饼果子;

(3)使用调用父类方法在__init__()和摊煎饼方法中处理。

复制代码
# 重写父类方法  子类继承父类后定义了一个和父类相同名字的方法
​
# 单继承的使用
class Master:
    name = '师父'
​
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
​
class Apprentice(Master):
​
    # 子类中定义了自己方法,和父类方法名一样
    # 子类相当于重写了父类的方法,在执行时按照子类的逻辑执行
    def flapjack(self):
        # 在子类中调用父类相同的方法  使用super()
        # 通过super可以获取父类对象
        print(super().name)
        print('摊手抓饼')
        super().flapjack()
​
​
a = Apprentice()
a.flapjack()

1-4 多层继承

(1)N年后,当初的徒弟也老了;

(2)因此,徒弟想要把"有自己品牌,也有黑马配方的煎饼果子"的所有技术传授给自己的小徒弟;

(3)请试着使用多层继承的方式完成案例。

复制代码
# 多层继承
# 重写父类方法  子类继承父类后定义了一个和父类相同名字的方法
​
# 单继承的使用
class Master:
    name = '师父'
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
​
class Apprentice(Master):
    name = '徒弟'
    def flapjack(self):
        print('摊手抓饼')
        super().flapjack()
​
​
​
class LittleApprentice(Apprentice):
    name = '小弟'
​
    def flapjack(self):
        print('蒸包子')
        super().flapjack()
        
​
# 创建对象
la = LittleApprentice()
la.flapjack()
​
print(LittleApprentice.__mro__)
​
复制代码
# 多层继承
# 重写父类方法  子类继承父类后定义了一个和父类相同名字的方法
​
# 单继承的使用
class Master:
    name = '师父'
    def flapjack(self):
        print('摊鸡蛋煎饼')
​
class School:
​
    name = '学校'
​
    def school_flapjack(self):
        print('摊肉肠煎饼')
​
​
class Apprentice(Master,School):
    name = '徒弟'
    def flapjack(self):
        print('摊手抓饼')
        super().flapjack()
​
​
​
class LittleApprentice(Apprentice):
    name = '小弟'
​
    def flapjack(self):
        print('蒸包子')
        super().flapjack()
        
​
# 创建对象
la = LittleApprentice()
la.flapjack()
la.school_flapjack()
print(LittleApprentice.__mro__)
​

二、多态

多态指的是一类事物的多中形态

相同的方法,产生不同的执行结果

运算符 + * 的多态

int + int 加法计算

str + str 字符串拼接

list + list 列表的数据合并


在python中可以使用类实现一个多态效果
在python中使用重写的方式实现多态

(1)定义两个类:老师、车;

(2)定义老师类的属性:姓名,定义老师类的方法:开车、停车;

(3)定义车类的属性:类型,定义车类的方法:开启、停止;

(4)联系:老师开车,执行程序,观察效果;

复制代码
# 多态
class Teacher:
​
    def __init__(self,name):
        self.name = name
​
    def run(self):
        print(f'{self.name}老师开车')
​
    def stop(self):
        print(f'{self.name}老师停车')
​
class Car:
​
    def __init__(self,type):
        self.type = type
​
    def start(self):
        print(f'{self.type}启动')
​
    def close(self):
        print(f'{self.type}熄火')
​
t = Teacher('张三')
c = Car('小汽车')
​
c.start()
t.run()
c.close()
t.stop()

使用继承方式,调整执行的方法

复制代码
# 多态
class Teacher:
​
    def __init__(self,name):
        self.name = name
​
    def run(self):
        print(f'{self.name}老师开车')
​
    def stop(self):
        print(f'{self.name}老师停车')
​
class Car(Teacher):
​
    def __init__(self,type,name):
        super().__init__(name)
        self.type = type
​
    def start(self):
        print(f'{self.type}启动')
        super().run()
    def close(self):
        print(f'{self.type}熄火')
        super().stop()
​
​
c = Car('小汽车','张三')
​
c.start()
c.close()

(5)思考:老师有可能开小轿车、骑自行车、坐地铁等,该怎么改进程序呢?

使用子类的重写功能实现多态
多态实现的流程

1-定义一个父类,在父类中定义需要执行的业务方法,具体方法的逻辑不用实现,直接pass,由继承的子类实现

2-定义多个功能的子类继承父类,在子类中对父类方法重写,实现自己子类的逻辑

3-封装一个统一的函数处理方法,让开发人员调用该方法

复制代码
# 多态
class Teacher:
​
    def __init__(self,name):
        self.name = name
​
    def run(self):
        pass
​
    def stop(self):
        pass
​
class Car(Teacher):
​
    def __init__(self,type,name):
        super().__init__(name)
        self.type = type
​
    def run(self):
        # 在多态实现时,子类继承父类并对父类方法进行重写
        print(f'{self.type}启动')
        print(f'{self.name}老师开车')
    def stop(self):
        print(f'{self.type}熄火')
        print(f'{self.name}老师停车')
​
class Metro(Teacher):
​
    def __init__(self,type,name):
        super().__init__(name)
        self.type = type
​
    def run(self):
        # 在多态实现时,子类继承父类并对父类方法进行重写
        print(f'{self.type}启动')
        print(f'{self.name}老师乘坐地铁')
        
    def stop(self):
        print(f'{self.type}到站')
        print(f'{self.name}老师下车')
​
​
# 单独封装一个行为函数
# 该函数就是对外提供一个函数接口,其他开发人员使用,就调用函数
def action(obj):
    # obj接收一个对象
    obj.run()
    obj.stop()
​
c = Car('越野车','张三')
action(c)
​
​
m = Metro('地铁1号线','李四')
action(m)
​

三、文件读写

通过文件读写完成对文件数据的处理
使用python中open方法实现对文件的读写

  • 格式

    • 会返回一个文件描述符

    • 使用文件描述符进行数据的读取或写入

复制代码
f = open(文件位置,读写方式,文件读写格式(utf-8,gbk))
​
data = f.read() 读取
f.write(数据) 写入
​
f.close() 关闭文件

3-1 文件数据读取

复制代码
# 文件数据读取
# 1-打开文件 创建文件描述符
# open的第一个参数指定读取的文件路径  可以使用绝对路径  也可以使用相对路径  windos的路径需要改斜杠
# 第二参数指定读写方式  r读 w写
# 第三个参数指定文件编码格式,方便读取中文数据  常用的两种utf-8  gbk
f = open('D/study/students.txt','r',encoding='utf-8')
​
# 读取数据文件
# 第一种 读取一行数据
# line_data1 = f.readline()
# print(line_data1)
# line_data2 = f.readline()
# print(line_data2)
​
# 第二种读取多行数据  将读取的多行数据放入列表中  该方式最常用
lines_data = f.readlines()
print(lines_data)
​
# 第三种  一次将所有数据读取出来当成一个完整的字符串数据  前面已经读取过数据 read就无法再读到数据 所以在实际开发中三种方式选择一种
# data = f.read()
# print(data)
# print(type(data))
​
​
# 数据取完成后可以使用close方法关闭文件
f.close()
​
​

3-2 数据写入文件

  • 写入方式

    • w 覆盖写入数据

    • a 追加写入数据

  • 写入类型

    • 要求写入数据是字符串类型
复制代码
# 文件数据写入
# 1-先打开文件获取文件描述符  文件描述符用来操作文件
# 使用相对路径   代码文件运行的所在路径
# csv文件是以逗号分割的数据文件  可以使用excel打开
# w是覆盖写入数据  a是追加写入数据
f = open('./data.csv','a',encoding='utf-8')
​
# 写入数据
f.write('3,王五,20,男')
f.write('\n') # 写入换行符  进行换行
f.write('4,赵六,22,男')
f.write('\n')
​
#关闭文件
f.close()

3-3 二进制文件读写

  • 图片,视频,音频

    • 在进行二进制文件数据读写时需要使用 rb ,wb
复制代码
# 二进制文件数据读写
# 1-打开文件获取文件描述符
f = open('D/study/1.jpeg','rb')
​
# 使用read一次性全部读取
data = f.read()
print(data)
# 关闭文件
f.close()
​
​
# 打开新的文件,将图片数据保存
f2 = open('./2.jpeg','wb')
​
f2.write(data)
​
f2.close()

3-4 with open 语法 读写文件

可以帮助开发人员在文件读写完成自动调用close

复制代码
# 使用with  open自动关闭文件
with open('D/study/students.txt','r',encoding='utf-8') as f:
    data = f.read()
    print(data)
​
​
with open('data.json','w',encoding='utf-8') as f:
    f.write('{"id":1,"name":"张三"}')
    f.write('\n')
    f.write('{"id":2,"name":"李四"}')
    f.write('\n')
  • 文件后缀

    • txt

    • csv

    • json

    • 文件后缀和文件的数据本身没有直接关系

    • 后缀只是为了说明可以使用那种工具打开该文件,方便识别文件类型

四、异常处理

在程序运行时出现的错误,使用对应方法时没有按照开发语言的要求使用

一旦出现错误,会中断代码的执行。

实际开发中需要对异常问题单独判断处理,保证程序能持续运行

捕获到异常后根据需求处理,也可以不处理

4-1 常见异常

索引错误
  • 索引下标异常,一般发生在数据取值
字典key值错误
  • key值错误 字典取值时错误
类型错误
  • 类型错误 多个数据进行计算时或出现的问题
文件错误
  • 读取文件时问价不存在
复制代码
# 索引下标取值错误
data = 'itcast'
data[100]
​
# 字典取值错误
data = {'name':'张三'}
data['age']
​
# 类型错误
data = '100'
data2 = 10
data3 = data/data2
​
# 文件读取错误 路径不存在
with open('aaa.txt','r',encoding='utf-8') as f:
    f.read()

4-2 异常捕获

通过语法捕获代码中的异常,根据异常信息,解决异常的问题,保证代码能持续运行

  • 格式
复制代码
try:
    需要捕获遗产干的代码片段,有开发人员自己决定哪些代码需要捕获
except:
    捕获到异常后处理的逻辑
复制代码
# 进行异常捕获
try:
    # 把出现的错误的代码逻辑放入try的作用域中
    data = 15/0
except:
    # 捕获到异常处理的业务逻辑
    print('异常被捕获')
# 异常被捕获后,可以正常执行后续的逻辑
print('其他代码逻辑')

4-3 指定异常类型捕获

复制代码
# 可以捕获所有异常
try:
    data_str = 'itcast'
    # data_str[100]
    f = open('aasd.txt','r',encoding='utf-8')
except:
    # 捕获到异常处理的业务逻辑
    print('异常被捕获')
    # 异常被捕获后,可以正常执行后续的逻辑
print('其他代码逻辑')
​
# 捕获固定的异常 处理固定错误
try:
    # data = 15/0
    # f = open('aasd.txt', 'r', encoding='utf-8')
    data_str='itcast'
    data_str[100]
# 捕获指定异常
except (FileNotFoundError,ZeroDivisionError,IndexError):
    print('捕获0为除数的异常')
print('其他代码逻辑')

4-4 异常的其他处理

可以在处理异常时编写没有异常的逻辑

复制代码
try:
    data = 15/0
    # Exception as e 获取异常的错误信息
    # 可以捕获到异常后输出错误信息
except Exception as e:
    print('异常被捕获')
    print(e)
else:
    print('else  没有异常逻辑')
finally:
    print('finally :无论是否有异常都执行')

4-5 函数中的异常处理

  • 在调用函数时进行异常捕获
复制代码
def func(a,b):
​
    data = a + b
    print(data)
​
try:
    # 调用其他开发人员编写的代码处理错误
    func('10',20)
except Exception as e:
    print(e)
​
  • 封装函数时异常捕获
复制代码
# 函数的异常处理
def func(a, b):
    data = 0
    # 在封装的函数内捕获异常
    try:
        data = a + b
    except:
        # 函数内自己处理异常
        print('异常错误')
    return data
​
​
# 调用函数
func(10,'20')
​
  • 函数内捕获到异常不处理,再传递给掉用函数的地方
复制代码
# 函数的异常处理
def func(a, b):
    data = 0
    # 在封装的函数内捕获异常
    try:
        data = a + b
    except:
        # 将异常的错误信息传递到调用地方 当前没有处理异常
        raise Exception('函数内计算错误')
    return data
​
​
​
# 调用函数时,捕获函数执行的异常
try:
    func(10,'20')
except Exception as e:
    print('异常捕获')
    print(e)
复制代码
# 多个函数中都要使用的变量可以定义成全局变量,通过global声明,就可在多个函数就可以共享全局数据
name_list = []
password_list = []
​
# 登录注册功能
def login():
    # 函数作用域
    # 通过四个空格,来确认函数所执行的逻辑从哪里开始
    # 列表,元组,集合,字典数据可以省略global声明
    15/0
    global name_list
    global password_list
    for num in range(3):  # [0,3)  0,1,2
        name = input('请输入用户名:')
        password = input('请输入密码:')
        # 先判断用户名是否正确
        if name in name_list:
            # 在判断密码是否正确
            if password in password_list:
                print('登录成功')
                # 适应break关键,会结束循环,不再进行取值
                break
            else:
                print('密码不正确')
        else:
            print('用户名不正确')
​
def register():
    global name_list
    global password_list
    name = input('请输入注册的用户名:')
    password = input('请输入出注册的密码:')
    # 将用户的名字和密码添加到全局的数据列表
    name_list.append(name)
    password_list.append(password)
​
while 1==1:
    num = input('1-登录 2-注册 3-支付 4-下单 5-退出程序:')
    if num == '1':
        # 函数功能的调用
        try:
            login()  # 函数名()
        except:
            print('登录出现错误')
    elif num == '2':
       register()
    elif num == '3':
        pass
    elif num == '4':
        pass
    else:
       break
复制代码
复制代码
相关推荐
小许学java4 分钟前
Spring AI快速入门以及项目的创建
java·开发语言·人工智能·后端·spring·ai编程·spring ai
AGG_Chan16 分钟前
flutter专栏--深入了解widget原理
开发语言·javascript·flutter
Darenm1111 小时前
JavaScript事件流:冒泡与捕获的深度解析
开发语言·前端·javascript
whltaoin1 小时前
Java 后端与 AI 融合:技术路径、实战案例与未来趋势
java·开发语言·人工智能·编程思想·ai生态
wjs20241 小时前
jEasyUI 自定义窗口工具栏
开发语言
二十雨辰1 小时前
vite与ts的结合
开发语言·前端·vue.js
xiaohanbao091 小时前
Transformer架构与NLP词表示演进
python·深度学习·神经网络
亦良Cool2 小时前
如何部署一个Java项目
java·开发语言
沐知全栈开发2 小时前
JavaScript 输出
开发语言
love530love2 小时前
【笔记】 Podman Desktop 中部署 Stable Diffusion WebUI (GPU 支持)
人工智能·windows·笔记·python·容器·stable diffusion·podman