9.异常处理
以下为常见的异常类型包括:
序号 | 类型 | 原因 |
---|---|---|
1 | ZeroDivisionError | 除0 |
2 | IndexError | 序列中没有该索引 |
3 | KeyError | 映射中没有这个键 |
4 | NameError | 未声明/初始化该对象 |
5 | SyntaxError | Python语法错误 |
6 | ValueError | 传入无效的参数 |
常用的异常处理语句:
1.try…except
需要写出具体的异常类型
try:
'可能出现异常的代码'
except '具体的异常类型':
'代码异常的处理代码'
2.try…except…except
多个except结构 捕获顺序按照先子类后父类的顺序
为了防止异常遗漏 最后通常加上BaseException
3.try…except…else
如果try中没有抛出异常,则执行else块;如果抛出异常,执行except块。
try:
'可能出现异常的代码'
except BaseException as e:
print('出错了,类型为',e)
else:
print('没出错就执行我')
4.try…except…else…finally
finally块无论是否发生异常都将继续执行,常用来释放try块申请的资源
try:
'可能出现异常的代码'
except BaseException as e:
print('出错了,类型为',e)
else:
print('没出错就执行我')
finally:
print('无论是否出差,我都会执行')
5.使用Traceback模板进行打印异常信息
import traceback #首先需要导入该模块
try:
num=10/0
except:
traceback.print_exc() #打印出异常信息
------------------------------------------------------
结果将会返回为:
Traceback (most recent call last):
File "D:\pythonProject1\try异常处理\demo1.py", line 6, in <module>
num=10/0
ZeroDivisionError: division by zero
10.面向对象编程
类与对象:
类的创建语法:
class 类名:
pass
类的组成通常包括:①类属性②实例方法③静态方法④类方法
类型 | 符号 | 例子 | 作用 | 用法 |
---|---|---|---|---|
类属性 | 被所有对象共享 | 类+.调用 | ||
实例方法 | def 方法名() | def func(self) ’括号内写self‘ | 类名直接访问的方法 | 实例化对象调用 |
静态方法 | @staticmethod | def func(cls) ’括号内cls‘ | 类名直接访问的方法 | 类+.调用 |
类方法 | @classmethod | def func() ‘括号内啥都不写’ | 类名直接访问的方法 | 类+.调用 |
对象的创建
对象的创建又称为类的实例化
语法: #有了实例,就可以调用类中的内容
实例名 = 类名()
stu1 = Student('张三')
动态绑定属性
可以为类添加初始化中未包含的属性
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print(self.name+'在吃饭')
A=Student('张三',12)
print(A.name,A.age)
A.gender='女' #Pyhton支持直接为类动态的添加新的属性 这里直接为类添加了gender属性
print(A.name,A.age,A.gender)
A.eat()
def show():
print('这是定义在类之外的函数')
A.show=show #动态的绑定方法 可以将类之外创建的函数 动态的添加到类中成为方法
A.show()
执行的结果为:
张三 12
张三 12 女
张三在吃饭
这是定义在类之外的函数
11.面向对象三大特征
- 封装–提高程序的安全性
1.将数据(属性)和行为(方法)包装到类里
2.Python中没有专属符号修饰属性的私有,若不希望该属性不被类对象外部访问,可以在其前边用两个’_’
class Student:
def __init__(self,name,age):
self.name=name
self.__age=age #此处的age属性设置为私有属性,外部直接对其访问时会报错
tips:这不是真的私有,仍可访问👇 可以但没必要!!!!:
print(A._Student__age) #对象._类名__属性名
- 继承–提高代码的复用性
1.语法格式:class 子类名称(父类1,父类2)
2.如果一个类都没有继承的话,Python是默认继承object类
3.Python支持多继承
4.定义子类式,需要在其构造函数中调用父类的构造函数:
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
class Student(Person):
def __init__(self,name,age,score): #构造函数写上所有的属性
super().__init__(name,age) #从父类继承时写上父类的所有属性
self.score=score #定义子类的属性
A=Student('张三',15,100)
print(A.name,A.age,A.score)
5.方法的重写:
如果子类对于继承父类某个属性或方法不满意时,可以对其进行重新编写
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def info(self):
print('姓名:{0},年龄{1}'.format(self.name,self.age))
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score=score
def info(self):
super().info() #也可以保持父类函数的功能
print('成绩:{0}'.format(self.score)) #可以直接重新新的方法
6.object类
objeck类是所有类的父类,可以使用内置函数dir()查看指定对象所有属性
其中object有一个__str()__方法,用于返回对对象的描述,可以对其进行重新来满足自己的需求
- 多态–提高程序的可扩展性和可维护性
多态,简单来说就是“具有多种形态”。
可以理解为:即便不知道一个变量所引用的对象是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用的对象的类型,动态地决定调用哪个对象中的方法。
class Animal(object):
def eat(self):
print('动物要吃东西')
class Dog(Animal):
def eat(self):
print('狗要吃香肠')
class Cat(Animal):
def eat(self):
print('猫要吃鱼')
class Person(object):
def eat(self):
print('人啥都吃')
def fun(obj):
obj.eat()
fun(Animal())
fun(Cat())
fun(Dog())
fun(Person())
语言 | 实现多态的区别 |
---|---|
静态语言 | 1.继承 2.方法重写 3.父类引用指向子类 |
动态语言 | 不需要关心对象是什么类型,只需要关心对象的行为 |
特殊属性和特殊方法
tips:object有一个__str()__方法,用于返回对对象的描述,可以对其进行重新来满足自己的需求
类的浅拷贝与深拷贝
①变量的赋值操作: 只是形成两个变量,实际上还是指同一个对象
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu=cpu
self.disk=disk
#(1)变量赋值
cpu1=CPU() #创建对象
cpu2=cpu1
print(cpu1,id(cpu1))
print(cpu2,id(cpu2))
打印输出的结果: 可以观察到cpu1和cpu2为同一个对象👇
<__main__.CPU object at 0x000001F222933FD0> 2139473788880
<__main__.CPU object at 0x000001F222933FD0> 2139473788880
②浅拷贝:
浅拷贝是指拷贝出一个新的对象,但是不拷贝原对象中包含的子对象内容。
使用copy模块的copy函数进行浅拷贝👇:
#类的浅拷贝
disk=Disk()
computer=Computer(cpu1,disk) #创建一个计算机类的对象
print(disk)
import copy
computer2=copy.copy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
打印输出的结果:
computer1和computer2的本身id不同,但包含的cpu和disk仍然是同一个👇
<__main__.Disk object at 0x000001F222933F70>
<__main__.Computer object at 0x000001F222933940> <__main__.CPU object at 0x000001F222933FD0> <__main__.Disk object at 0x000001F222933F70>
<__main__.Computer object at 0x000001F222933850> <__main__.CPU object at 0x000001F222933FD0> <__main__.Disk object at 0x000001F222933F70>
#computer1和computer2的本身id不同,但包含的cpu和disk仍然是同一个
③深拷贝:
深拷贝是指除了对原对象拷贝出一个新的对象外,对原对象中的所有子类也进行新的拷贝。
使用copy模块的deepcopy函数进行浅拷贝👇:
#深拷贝
computer3=copy.deepcopy(computer)
print(computer,computer.cpu,computer.disk)
print(computer3,computer3.cpu,computer3.disk)
打印输出的结果:
computer1和computer2的本身id不同,且包含的cpu和disk也不同👇
<__main__.Computer object at 0x000001F222933940> <__main__.CPU object at 0x000001F222933FD0> <__main__.Disk object at 0x000001F222933F70>
<__main__.Computer object at 0x000001F222933760> <__main__.CPU object at 0x000001F2229333A0> <__main__.Disk object at 0x000001F222933340>
#computer1和computer2的本身id不同,且包含的cpu和disk也不同
总结:
拷贝类型 | 方法 | 特点 |
---|---|---|
变量赋值 | 直接进行赋值操作 | 两者仍然是同一个对象 |
浅拷贝 | 使用copy.copy()进行操作 | 只拷贝原对象,不拷贝其子对象 |
深拷贝 | 使用copy.deepcopy()进行操作 | 同时拷贝原对象和其子对象 |
12.模块化编程
模块英文为Modules,一个模块中可以包含多个函数
在Python中一个扩展名为.py的文件就是一个模块
使用模块的好处:
- 方便其他程序和脚本的导入及使用
- 避免函数名和变量名冲突
- 提高代码的可维护性
- 提高代码的可重用性
1.模块的导入
模块的导入方式通常分为两种:
①import 模块名称 [as 别名]
②from 模块名称 import 函数/变量/类
import math #关于数学运算模块
print(math.pi) #调用变量时需要加上模块名 的前缀
from math import pi
print(pi) #直接调用变量
2.以主程序方式运行
当我们在调用一些模块时只希望使用其中的部分语句时,我们可以将剩余的语句设置为只在以主程序形式运行时才执行:
以下为一个calculate模块,我们在调用时只希望执行计算功能,而不使用print函数的打印功能,即可将print语句放置在_main_下,即可实现👇:
def add(a,b):
return a+b
if __name__ == '__main__':
print('---------') #只有运行calc这个文件(将calc作为主程序)时,这条语句才会被执行
3.Python中的包
包,是一个分层次的目录结构,目的是将功能相近的模块组织在一个目录下
作用:
①代码规范
②避免模块名冲突
包与目录的区别:
包含__init__.py文件的目录称为包
包的导入方式:
①import …
②from … import …
两者的区别在于:
①使用import进行导入时,只能跟包名或模块名
②使用from…import 可以导入包,模块,类名,变量
Python中常见的内置模块👇:
例如:
import sys #python解释器相关
import urllib #这是一个包
print(sys.getsizeof(24)) #28
print(sys.getsizeof(45)) #28
print(sys.getsizeof(True)) #28
print(sys.getsizeof(False)) #14
print('----------------------')
import time #与时间相关的
print(time.time())
print(time.localtime(time.time()))
输出结果👇:
28
28
28
24
----------------------
1631339216.7994924
time.struct_time(tm_year=2021, tm_mon=9, tm_mday=11, tm_hour=13, tm_min=46, tm_sec=56, tm_wday=5, tm_yday=254, tm_isdst=0)
第三方模块的安装及使用:
- 第三方模块安装: Win+R打开控制界面后输入: pip install 模块名
- 第三方模块使用: 在使用前导入 import 模块名
以下使用了第三方模块schedule 实现定时输出任务👇:
import schedule
import time
def job():
print('哈哈哈哈')
schedule.every(3).seconds.do(job)
while True:
schedule.run_pending()
time.sleep(1)
13.文件操作
1.编码格式:
常见的编码格式包括:
①Python的解释器使用的时Unicode(内存)
②.Py文件在磁盘上使用UTF-8存储(外存)
不同的编码格式往往会导致文件存储的字节数目不同,且在不同编码情况下打开文件可能出现乱码的情况
可以在文件顶部选择文件的保存方式 不写的话默认的是UTF-8👇:
#encoding=gbk
........
2.文件操作
文件的读写操作通常称为IO操作。
文件的读操作:file(文件对象)=open(操作函数)( filename(文件名) [,mode(打开模式),encoding(编码方式)])
文件类型通常包括:
①文本文件:存储的是普通“字符”文本,默认为Unicode字符集,可以用记事本打开
②二进制文件:把数据用二进制存储,无法用记事本打开,例如.MP3 .JPG文件
对文件操作常用的打开模式:
方式 | 作用 |
---|---|
‘r’ | ‘read’只对文件进行读取操作 |
‘w’ | 'write’只对文件进行写操作 |
‘a’ | 对文件进行追加操作,可以为文件添加内容 |
文件对象的常用方法:
tips:为了防止忘记写file.close()操作,我们可以使用with语句👇:
with open('a.txt','r') as file:
print(file.read())
这样可以使得执行结束后自动关闭打开的文件
3.OS模块的常用函数:
OS模块是Python内置的 与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统相关。
os模块与os.path模块用于对目录或文件进行操作👇:
import os
os.system('notepad.exe') #打开记事本
os.system('calc.exe') #打开计算器
#直接调用可执行文件
os.startfile('D:\Tencent\QQ\Bin\QQScLauncher.exe') #运行我的QQ
常见的模块操作目录相关函数
运行实例👇:
import os
print(os.getcwd()) #输出当前工作目录
lst=os.listdir('../chap10') #返回指定路径下的文件和目录信息
print(lst)
os.mkdir("newdir2") #创建目录
os.makedirs('A/B/C') #创建多级目录
os.rmdir('newdir2') #删除指定目录
os.removedirs('A/B/C') #删除多级目录
os.chdir('D:\pythonProject1\chap10') #切换工作目录
print(os.getcwd())
执行结果:
D:\pythonProject1\chap14
['demo1.py', 'demo2.py', 'demo3.py', 'demo4.py', 'demo5.py', 'demo6.py', 'demo7.py']
D:\pythonProject1\chap10
常见的os.path模块操作目录相关函数:
运行实例👇:
import os.path
print(os.path.abspath('demo4.py')) #获取文件或目录的绝对路径
print(os.path.exists('demo8.py'),os.path.exists('demo12.py')) #判断是否存在
print(os.path.join('D:\\Python','demo13.py')) #拼接
print(os.path.split('D:\\Python\\demo8.py')) #将目录与文件进行拆分
print(os.path.splitext('demo8.py')) #将文件与后缀名拆分
print(os.path.basename('D:\\Python\\demo66.py')) #提取文件名
print(os.path.dirname('D:\\Python\\demo66.py')) #提取目录名
print(os.path.isdir('D:\\Python\\demo66.py')) #判断其是否是目录 这里为False是因为它是文件
执行结果👇:
D:\pythonProject1\chap14\demo4.py
True False
D:\Python\demo13.py
('D:\\Python', 'demo8.py')
('demo8', '.py')
demo66.py
D:\Python
False