Python的异常处理机制
Bug的常见类型
- 被动掉坑的解决方案
- python提供了异常处理机制,可以在异常出现时即使捕获,然后内部'消化'让程序继续运行
- 语法
- 如果出现多个异常则可以使用,多个except结构,捕获异常的顺序按照先子类后父类的顺序为了避免漏洞可能出现的异常,可以在最后增加BaseException
try:
a=int(input('请输入第一个整数'))
b=int(input('请输入第二个整数'))
result=a/b
print('结果是',result)
except ZeroDivisionError:
print('sorry you input data ZeroDivisionError')
except ValueError:
print('sorry you input data ValueError')
except BaseException:
print('sorry you input data BaseException')
try...except..else结构
- 如果try中没有异常,则执行else块,如果try抛出异常,则执行except块
try:
a=int(input('请输入第一个整数'))
b=int(input('请输入第二个整数'))
result=a/b
except ZeroDivisionError:
print('sorry you input data ZeroDivisionError')
except ValueError:
print('sorry you input data ValueError')
except BaseException:
print('sorry you input data BaseException')
else:
print('结果是',result)
try...except..else..finally结构
- 如果try中没有异常,则执行else块,如果try抛出异常,则执行except块,finally无论是否异常都会执行
try:
a=int(input('请输入第一个整数'))
b=int(input('请输入第二个整数'))
result=a/b
except ZeroDivisionError:
print('sorry you input data ZeroDivisionError')
except ValueError:
print('sorry you input data ValueError')
except BaseException:
print('sorry you input data BaseException')
else:
print('结果是',result)
finally:
print('------结束资源代码')
python常见的错误类型
异常类型 | 描述 |
---|---|
ZeroDivisionError | 除或取模零所有数据类型,数学运算异常 |
IndexError | 序列中没有此索引 |
KeyError | 映射中没有这个键 |
ValueError | 传入无效的参数 |
NameError | 未生名/初始化对象 |
SyntaxError | python语法错误 |
处理异常的机制,traceback模块
使用traceback模块打印异常信息
import traceback
try:
a=int(input('请输入第一个整数'))
b=int(input('请输入第二个整数'))
result=a/b
except ZeroDivisionError:
print('sorry you input data ZeroDivisionError')
traceback.print_exc()
except ValueError:
print('sorry you input data ValueError')
traceback.print_exc()
except BaseException:
print('sorry you input data BaseException')
traceback.print_exc()
else:
print('结果是',result)
finally:
print('------结束资源代码')
代码调试,这个太简单了不讲了;要根据使用的idea工具来定
对象
- 编程界的两大阵营
概念
类型 | 面向过程 | 面向对象 |
---|---|---|
区别 | 事物比较简单,可以用线性思维去解决 | 事物比较复杂时,使用简单的线性思维无法解决 |
共同点 | 面向过程和面向对象都是解决问题的一种思维方式 | |
二者相辅相成,并不是对立的,解决复杂问题通过面向对象方式便于我们从宏观上把我事物之间的复杂关系,方便我们分析整个系统,具体到微观操作,仍然使用面向过程来处理 |
-
类:类别,分门别类,物以类聚,人类,鸟类,植物类,动物类,类是多个类似事物组成的群体的统称,能够帮助我们快速理解和判断的事物的性质;
-
数据类型:不同的数据类型属于不同的类,使用内置函数可以查看类型type()
-
对象:100,99,50都是int类之下包含的相似的不同个例,这个个例专业术语称为实例或对象
python一切皆对象; -
类的创建
- 语法class student: pass
- 组成:类属性,实例方法,静态方法,类方法
from traceback import print_tb
from turtle import st
class Student:
def __init__(self,name,age): # self.name称为实例属性,进行了一个赋值操作,将局部的name赋值给实体属性
self.name=name
self.name=name
def eat(self): #实例方法需要增加self
print('chifan')
@staticmethod #静态方法不需要增加self
def methode():
print('my staticMethod')
@classmethod #类方法需要增加cls
def classm(cls):
print('my classMethod')
pass
#类名由一个或者多个单词组成,要求每个单词的首字母大写,其余小写,类创建了就有了内存地址id,类型
print(id(Student))
print(type(Student))
print(Student)
# 1913667383408
# <class 'type'>
# <class '__main__.Student'>
- 对象的创建
- 语法
- 意义:有了实例,就可以调用类中的内容
- 分为类对象,实例对象,创建时类实例对象创建时会调用类对象的info函数,类指针,实例对象指向那个类对象;
class Student:
def __init__(self,name,age): # self.name称为实例属性,进行了一个赋值操作,将局部的name赋值给实体属性
self.name=name
self.age=age
pass
def eat(self): #实例方法需要增加self
print('chifan')
pass
@staticmethod #静态方法不需要增加self
def methode():
print('my staticMethod')
pass
@classmethod #类方法需要增加cls
def classm(cls):
print('my classMethod')
pass
stu1=Student('zhangsan',18)
# print(id(stu1))
# print(type(stu1))
# print(stu1) # 默认输出对象的十六进制的内存地址
# print(id(Student))
# print(type(Student))
# print(Student)
stu1.eat()# 对象调用
print(stu1.name)
print(stu1.age)
Student.eat(stu1)#类名调用方法,实际上就是方法定义处的self
类属性,类方法,静态方法
- 类属性: 类中方法外的变量称为类属性,该类的所有对象所共享
- 类方法:使用@classmethod修饰的方法,使用类名直接访问的方法
- 静态方法:使用@staticmethod修饰的方法,使用类名直接访问的方法;
class Student:
money=10 # 类属性
def __init__(self,name,age):
self.name=name
self.age=age
pass
def eat(self,d='龙虾'):
print('我们今天吃大餐:'+d)
pass
@staticmethod
def exe():
print('我们都会走路')
pass
@classmethod
def cm(cls):
print('我是类方法,只要我是人类,我会使用工具')
pass
# 类属性调用
print(Student.money)
stu1=Student('张三',10)
stu2=Student('李四',20)
Student.money=22
print(stu1.money)
print(stu2.money)
# 类方法使用方式
Student.cm()
# 静态方法
Student.exe()
python是动态语言,在创建对象之后,可以动态的绑定属性和方法
class Student:
def __init__(self,name,age) -> None:
self.name=name
self.age=age
pass
def eat(self):
print(self.name,'正在吃饭')
pass
pass
stu1=Student('里斯',55)
# 动态添加属性
stu1.gender='女'
stu2=Student('王五',11)
print(id(stu1))
print(id(stu2))
print(id(Student))
# print(stu1.age,stu1.name,stu1.gender)
# print(stu2.age,stu2.name,stu2.gender)
stu1.eat()
stu2.eat()
def show():
print('我是定义类之外的函数')
pass
stu1.show=show
stu1.show()
面向对象的三大特征
- 封装
- 提高程序的安全性
- 将数据(属性)和行为(方法)包装到类对象中,在方法内对属性进行操作,在类对象的外部调用方法.这样无需关心方法内部具体实现的细节,从而隔离了复杂程度
- 在python没有专门的修饰符用于属性的私有,如果该属性不希望类对象外部被访问,前面使用两个__表示
- 提高程序的安全性
- 继承
- 提高代码的复用性,python支持多继承,也可以间接集成,默认都进程Object,定义子类时,必须在其构造函数中调用父类的构造函数;
- 多态
- 提高程序的可扩展性和维护性,
- 简单地说,多态就是具有多中形态,他指的是即便不知道一个对象所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用的对象的类型,动态的决定调用那个对象中的方法.python的多态和继承无关,只要都有这个方法就可以了;
- 提高程序的可扩展性和维护性,
封装
class Student:
def __init__(self,name,age):
self.name=name
self.__age=age
pass
def show(self):
print(self.name,self.__age)
pass
pass
stu=Student('张三',22)
stu.show()
# print(stu.name,stu.__age) AttributeError: 'Student' object has no attribute '__age' 当程序在运行时发现是__则视为私有属性,在外部就不可以调用了
# print(dir(stu)) 打印该类可以使用的方法
# print(stu._Student__age) 在类的外部可以通过_Student__age进行访问
继承
class Persion(object):# Persion extends Object
def __init__(self,name,age):
self.name=name
self.age=age
pass
def info(self):
print(self.name,self.age)
pass
class Student(Persion):
def __init__(self,name,age,stu_no):
super().__init__(name,age)
self.stu_no=stu_no
pass
pass
class Teacher(Persion):
def __init__(self,name, age,teacho):
super().__init__(name,age)
self.stu_no=teacho
pass
pass
stu=Student('张三',20,'1101')
teracher=Teacher('李四',34,10)
stu.info()
Teacher.info(teracher)
class A(object):
pass
class B(object):
pass
class C(A,B):# 多继承
pass
重写
重载:python中可以设置两个相同的方法,如果方法相同则第二个会将第一个进行覆盖;
class Persion(object):# Persion extends Object
def __init__(self,name,age):
self.name=name
self.age=age
pass
def info(self): # 如果不加上self在对象调用这个方法时会出现 Persion.info() takes 0 positional arguments but 1 was given
print(self.name,self.age)
pass
class Student(Persion):
def __init__(self,name,age,stu_no):
super().__init__(name,age)
self.stu_no=stu_no
pass
def info(self):
super().info() # 重载这个方法,如果还想使用父类的方法就需要使用super()进行调用了
print(self.name,self.age,self.stu_no)
pass
pass
class Teacher(Persion):
def __init__(self,name, age,teacho):
super().__init__(name,age)
self.stu_no=teacho
pass
pass
stu=Student('张三',20,'1101')
teracher=Teacher('李四',34,10)
stu.info()
Teacher.info(teracher)
object类
- object类是所有类的父类,因此所有类都有object类的属性和方法.
- 内置函数dir()可以查看指定对象所有的属性和方法
- Object有一个str()方法,用户返回一个对于对象的描述,对应内置函数str(),经常用于print()方法,帮我们查看对象的信息,所以我们经常会对str()进行重写
多态
class Animal(object):
def eat(self):
print('动物会吃')
pass
class Dog(Animal):
def eat(self):
print('狗吃骨头...')
pass
class Cat(Animal):
def eat(self):
print('猫吃鱼')
pass
class Persion:
def eat(self):
print('人吃五谷杂粮')
pass
def fun(obj):
obj.eat()
pass
fun(Cat())
fun(Dog())
fun(Animal())
静态语言和动态语言关于多台的区别
静态语言实现多态的三个必要条件
- 继承
- 方法重写
- 父类引用指向子类对象
- 多态语言的多态崇尚'鸭子类型',当看到一只鸟走起来像鸭子,游起来像鸭子,收起来也像鸭子,那么这只鸟就可以被称为鸭子,在鸭子类型中,不需要关系对象是什么类型,到底是不是鸭子,只关心对象的行为.方法
概念 | 方法 | 描述 |
---|---|---|
特殊属性 | dict | 获得类对象或实例对象所绑定的所有属性和方法的字典 |
特殊方法 | len() | 通过重写len()方法,让内置函数len()的参数可以是自定义类型 |
特殊方法 | add() | 通过重写add()方法,可以使用自定义对象具有'+'功能 |
特殊方法 | new() | 用于创建对象 |
特殊方法 | init() | 创建的对象进行初始化 |
特殊的属性下方:
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name) -> None:
super().__init__()
self.name=name
pass
pass
x=C('jeck')
print(x.__dict__) # 实例对象的属性
print(C.__dict__)# 类对象的属性
print(x.__class__) #对象所属的类
print(C.__bases__)# 输出C类的父类的元组
print(C.__base__)# 输入第一个父类
print(C.__mro__)# 类的层次结构
print(A.__subclasses__)# 输出该类的子类
# a =20
# b = 200
# c=a+b # 两个整数的对象的相加操作
# d=a.__add__(b)
# print(d)
class Student:
def __init__(self,name):
self.name=name
def __add__(self,oher):#重写该方法可以使对象可以进行相加
return self.name+oher.name
def __len__(self):
return self.name.__len__()
stu1=Student('zhangsan')
stu2=Student('lisi')
s=stu1+stu2
print(s)
print(len(stu1))
class Person():
def __init__(self,name,age): # 注意init方法是不能return其他内容的否则就是 __init__() should return None, not 'Person'
print('self的id为',id(self))
self.name=name
self.age=age
pass
def __new__(cls,*args,**kwargs):# 在调用Person('张三',20)时就会先执行new方法,如果不写默认是object执行调用,在这里只是重写了一下,注意这里要teturn obj不然不会调用该对象的init方法,在这个new方法主要是创建对象用的,创建完对象后对象该对象的object属性方法配置完成
print('new被调用执行了,cls值为',id(cls))
obj=super().__new__(cls)
print('obj创建对象的id',id(obj))
return obj
print('object这个类对象的id为',id(object))
print('persion这个对象类对象id为{0}'.format(id(Person)))
p=Person('张三',20)
print('p1这个persi类对象实例对象的id是{0}'.format(id(p)))
类的浅拷贝与深拷贝
- 变量的赋值操作
- 只是形成两个变量,实际上还是执行一个对象
- 浅拷贝
- python拷贝一般都是浅拷贝,拷贝时,当前对象可以拷贝成功,但是当前对象包含的子对象,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象引用同一个子对象
- 深拷贝
- 使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的对象及子对象都不相同
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk) -> None:
self.cpu=cpu
self.disk=disk
# 变量赋值
cpu1=CPU()
cpu2=cpu1
print(cpu2,id(cpu1))
print(cpu1,id(cpu2))
# 类的浅拷贝
disk=Disk()
computer=Computer(cpu1,disk)
# 浅拷贝
import copy
computer2=copy.copy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
# 只有computer2id不同剩余的cpu,disk的id一致
# 深拷贝
print('-------------------------------')
computer3=copy.deepcopy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
print(computer3,computer3.cpu,computer3.disk)

模块
- 概念:模块英文为Modules
- 函数与模块的关系
- 一个模块中可以包含多个N多个函数
- 在Python中一个扩展名为.py文件就是一个模块
- 使用模块的好处
- 方柏霓其他程序和脚本的导入并使用
- 避免函数名和变量名冲突
- 提高代码的可维护性
- 提高代码的可重用性
- 自定义模块
- 创建模块,新建一个.py文件,名称尽量不要与python自带的标准模块相同
- 导入模块
- python中的包
- 包是一个分层次的目录结构,它是将一组相近的模块组织在一起
- 作用:代码规范,避免模块名冲突
- 包与目录的区别
- 包含init.py文件的目录称为包
- 目录里通常不包含__init__py文件
# 在这里导入pageage1的包
import pageage1.module1 as ma
# 使用import进行导入时,只能跟包名或者跟模块名
from pageage1.module1 import a
from pageage1 import module1
# 使用from...import可以导入包,模块,函数,变量
print(ma.a)
import demo3 as dd
print(dd.name)
import math as m
print(id(m))
print(type(m))
print(m)
print(m.pi)
print(dir(m))
print(m.pow(2,3),type(m.pow(2,3)))
print(m.ceil(9.001))
print(m.floor(9.999))
# as 是别名
#第二种方式,导入指定的属性,方法,对象
from math import pi
print(pi)
以主程序的形式运行
- 在每个模块定义中都包含一个记录模块名称的变量name,程序可以检查该变量,以确认他们在哪个模块中执行.如果一个模块不是被导入到其他程序中执行,那么它可能在解释器的顶级模块中执行,顶级模块的name变量的值为main
from tkinter.tix import MAIN
from pip import main
def add(a,b):
return a+b
if __name__ =='__main__':
print(add(20,20)) # 只有当点击运行test时才会去执行该语句
# demo3.py文件进行运行,如果没有写入到main方法中,在执行demo3.py时,会连续输出两次结果30,30
import test
print(test.add(10,20))
python中常用的内置模块
模块名 | 描述 |
---|---|
sys | 与Python解释器及其环境操作相关的标准库如:print(sys.getsizeof(24)) #获取对象所占的内存大小; |
time | 提供与时间相关的各种函数的标准库 |
os | 提供了访问操作系统功能的标准库 |
calendar | 提供了与日期相关的各种函数的标准库 |
urllib | 用于读取来自网上(服务器)的数据标准库 |
json | 用于使用json序列化和反序列化对象 |
re | 用于在字符串中执行正则表达式匹配和替换 |
math | 提供标准算数函数的标准库 |
decimal | 用于进行精确控制运算精度,有效数位和四舍五入操作的十进制运算 |
logging | 提供了领过记录事件,错误警告和调试信息等日志信息的功能 |
import time
print(time.time())
print(time.localtime())
print(time.localtime(time.time()))
from urllib import request
print(request.urlopen('http://www.baidu.com').read())
第三方模块的安装
pip install 模块名
使用第三方模块import 模块名
编码格式
- 编码格式
- 创建的编码格式,python的解释器使用的时unicode(内存)
- .py文件在磁盘上使用UTF-8存储(外存)
- 文件的读写原理
- 文件读写操作
- 文件对象常用的方法
- with语句(上下文管理器)
-
目录操作
d297a43fff37433494dda6479958efd.png
file=open(r'C:\Users\sj176\Desktop\学习\pageage1\a.txt','r')
print(file.readlines())# 读取文件当中的所有内容
file.close()
- 常用的文件打开模式
- r读取文件:文件的指针会放在文件的开头
- w以只写模式打开文件:如果文件不存在则进行创建,如果文件存在,则进行覆盖原有内容,文件指针在文件的开头
- a以追加的方式进行打开文件(这个a不会r读文件),如果文件不存在则创建,文件指针在文件开头,如果文件存在则在文件末尾处追加内容,文件指针在末尾
- b以二进制的方式打开文件,不能单独使用,需要与其他模块一起使用,rb或者wb
- +以读写的方式打开文件,不能单独使用,需要与其他模块一起使用,a+,r+,w+
- 文件对象的常用方法
- read(size)从文件中读取size个字节或字符内容返回.诺省略不写size则读取到文件末尾,即一次读取完毕
- readline()从文件中读取一行
- readlines()从文件中读取每一行,将数据按行放入列表中
- write(str)将字符串str内容写入文件
- writelines(list)将字符串列表写入文本文件,不添加换行符
- seek(offset[,whence])把文件指针移动到最新的位置,offset表示相对于whence的位置:
- offset为正往结束方向移动,为负往开始方向移动
- whence不同的值代表不同含义
- 0 从文件开头开始计算(默认值)
- 1从当前位置开始计算
- 2从文件末尾开始计算
- flush将缓存区域内存的数据刷新到硬盘上
- tell返回文件指针的当前位置
# file=open(r'C:\Users\sj176\Desktop\学习\pageage1\a.txt','a+') # 如果是图片文件,就需要二进制的方式进行打开啦
# print(file.read())# 读取文件当中的所有内容
# # file.write('123')
# file.close()
file=open(r'C:\Users\sj176\Desktop\学习\pageage1\a.txt','r',encoding='utf-8')
file.seek(3)#将指针移动到第二个字节,如果是中文的话需要考虑文件的字符编码,UTF-8的中文占用3个所以写3跳过第一个字
print(file.read())
print(file.flush())# 将缓存区的数据写入到硬盘
print(file.tell())# 查看文件指针的当前位置
file.close()# 关闭资源
with语句(上下文管理器)
- with语句可以自动管理上下文资源,不论什么原因跳出with快,都能确保文件正常的关闭,以此来达到释放资源的目的
# file=open(r'C:\Users\sj176\Desktop\学习\pageage1\a.txt','a+') # 如果是图片文件,就需要二进制的方式进行打开啦
# print(file.read())# 读取文件当中的所有内容
# # file.write('123')
# file.close()
filePath=r'C:\Users\sj176\Desktop\学习\pageage1\a.txt'
with open(filePath,'r') as file: # 自动调用__enter__()方法并将返回值赋值给file
strd=file.read()
print(strd)
# 当离开上下文,自动调用上下文管理器的特殊方法__exit__()
# 使用上下文管理器进行复制图片
file=r'C:\Users\sj176\Desktop\学习\meishaonv.jpg'
with open(file,'rb') as fi:
with open('ddd.jpg','wb') as w:
w.write(fi.read())
# 类对象遵守了上下文管理器协议,实现__enter__和__exit__,该类的实例对象称为上下文管理器,
class MyContentMgr():
def __enter__(self):
print('我是__enter__')
return self
def __exit__(self,exc_type,exc_val,exc_tb):
print('is __exit__')
def show(self):
print('show 方法被调用了')
with MyContentMgr() as file:
file.show() # 是否产生异常,都会调用该对象的__exit__()的方法
filePath=r'C:\Users\sj176\Desktop\学习\pageage1\a.txt'
with open(filePath,'r') as file: # 自动调用__enter__()方法并将返回值赋值给file
strd=file.read()
print(strd)
# 当离开上下文,自动调用上下文管理器的特殊方法__exit__()
目录操作
- os模块是python内置的与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上运行,得到的结果可能不一样.
- os模块与os.path模块用于对目录或文件操作
- 操作目录的相关函数
- getcwd()# 获取当前工作目录
- listdir(path)返回指定路径下的文件和目录信息
- mkdir(path[,mode])创建目录
- makedirs(path,[,mode])创建多级目录
- rmdir(path)删除一级目录
- removedirs()删除多级目录
- chdir()设置目录为当前工作控件
- walk(path)遍历该迭代器对象返回回来的就是一个元组,包含该文件及其子文件夹子文件,的所有数据;
- os.path模块的目录相关函数
- abspath获取该文件的绝对路径
- exists判断文件或目录是否存在
- isdir判断目录是否是一个已存在的目录
- join目录和文件名进行拼接返回拼接后的地址
- split将文件和目录进行拆分
- splitext拆分文件与后缀名
- basename从文件地址中提取文件名
- dirname从文件地址中提取目录地址
filePath=r'C:\Users\sj176\Desktop\学习\pageage1\a.txt'
import os
# os.system('notepad.exe') # 打开记事本notepad.exe和win+r输入的效果一样的
# os.system('calc.exe')
# 直接调用可执行文件
# os.startfile(r'D:\A098 V25.915\Dead Cells Practice Makes Perfect\deadcells.exe') # 打开执行系统文件
# lst=os.listdir('学习') # 写入../cd/退到上级目录
# print(lst)
# os.mkdir('学习/test') # 创建一级目录
# os.makedirs('学习/a/v/c/d/d') # 创建多级目录
# os.rmdir('a') # 移除一级目录
# os.removedirs('学习/a/v/c/d/d') # 移除多级目录
os.chdir('E:\\VIP\\cc') # 设置目录为当前工作控件
import os.path
print(os.path.abspath('ddd.jpg')) # 获取绝对路径
print(os.path.exists('test')) # 用于判断文件或目录是否存在,如果存在返回Ture不存在返回False
print(os.path.join('E:\\python','ddd.jpg')) # 目录和文件名进行拼接返回拼接后的地址
path=os.path.join('E:\\python','ddd.jpg')
print(os.path.split(path)) # 将文件和目录进行拆分
print(os.path.splitext(path)) #拆分文件与后缀名
print(os.path.basename(path)) # 从文件地址中提取文件名
print(os.path.dirname(path)) # 从文件地址中提取目录地址
print(os.path.isdir(path)) #用于判断是否是一个已存在的路径
迭代遍历所有文件及子文件夹
import os
path=os.getcwd()
lst_files=os.walk(path)
print(lst_files)
for dirpath,dirname,filename in lst_files:
for dir in dirname:
print(os.path.join(dirpath,dir))
for file in filename:
print(os.path.join(dirpath,file))
print('--------------')
网友评论