一、异常处理
python解释器检测到错误,触发异常(也允许程序员自己触发异常)。程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)。如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理。
python解释器去执行程序,检测到了一个错误时,触发异常,异常触发后且没被处理的情况下,程序就在当前异常处终止,后面的代码不会运行,谁会去用一个运行着突然就崩溃的软件。所以你必须提供一种异常处理机制来增强你程序的健壮性与容错性。良好的容错能力,能够有效的提高用户体验,维持业务的稳定性。
程序运行中的异常可以分为两类:语法错误和逻辑错误。首先,我们必须知道,语法错误跟异常处理无关,所以我们在处理异常之前,必须避免语法上的错误。
异常就是程序运行时发生错误的信号,在python中,错误触发的异常如下
1.1 异常处理方式
1.1.1 使用if判断式
# 我们平时用if做的一些简单的异常处理 num1 = input('>>: ') # 输入一个字符串试试 if num1.isdigit(): int(num1) # 我们的正统程序放到了这里,其余的都属于异常处理范畴 elif num1.isspace(): print('输入的是空格,就执行我这里的逻辑') elif len(num1) == 0: print('输入的是空,就执行我这里的逻辑') else: print('其他情情况,执行我这里的逻辑') # 这些if,跟代码逻辑并无关系,显得可读性极差,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。
使用if判断式可以异常处理,但是if判断式的异常处理只能针对某一段代码,对于不同的代码段的相同类型的错误你需要写重复的if来进行处理。而且在你的程序中频繁的写与程序本身无关,与异常处理有关的if,会使得你的代码可读性极其的差。
1.1.2 python提供的特定的语法结构
part1:基本语法
try: 被检测的代码块 except 异常类型: try中一旦检测到异常,就执行这个位置的逻辑
part2:单分支
a = [1,2,3] d = {} try: a[3] print(d['name']) except IndexError as e: print('下标越界',e) except KeyError as e: print('字典key不存在') else: print('正常运行')
下标越界 list index out of range
finally: 有没有出现异常都走这
a = [1,2,3] d = {} try: a[3] print(d['name']) except Exception as e: # 所有异常都能捕捉到 print('出异常了',e) else: print('正常运行') finally: print('有没有出现异常都走这')
出异常了 list index out of range 有没有出现异常都走这
异常处理try except用法中,如果使用了return就不需要使用else
try: cur.execute(sql) except Exception as e: print('mysql连接失败,%s' %sql) # result = False # 如果使用了return 就不需要使用else else: ...
part3:多分支
l1 = [('电脑',16998),('鼠标',59),('手机',8998)] while 1: for key,value in enumerate(l1,1): print(key,value[0]) try: num = input('>>>') price = l1[int(num)-1][1] except ValueError: print('请输入一个数字') except IndexError: print('请输入一个有效数字') #这样通过异常处理可以使得代码更人性化,用户体验感更好。
part4:万能异常
在python的异常中,有一个万能异常:Exception,他可以捕获任意异常。它是一把双刃剑,有利有弊,我们要视情况使用
如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么只有一个Exception就足够了。
如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。我们可以使用多分支+万能异常来处理异常。使用多分支优先处理一些能预料到的错误类型,一些预料不到的错误类型应该被最终的万能异常捕获。需要注意的是,万能异常一定要放在最后,否则就没有意义了。
except Exception as e: 所有异常都能捕捉到
1 a = [1,2,3] 2 d = {} 3 try: 4 a[3] 5 print(d['name']) 6 except Exception as e: # 所有异常都能捕捉到 7 print('出异常了',e) 8 else: 9 print('正常运行')
出异常了 list index out of range
part5:try...else语句
try: for i in range(10): int(i) except IndexError as e: print(e) else: print('***********') #*********** 执行了此处 #当try语句中的代码没有异常,被完整地执行完,就执行else中的代码
小结
try: # 可能发生异常的代码 except 异常类型1 as 变量名: print(变量名) # 变量名存储的是具体的错误信息 except 异常类型2 as 变量名: print(变量名) # 变量名存储的是具体的错误信息 except Exception as 变量名: print(变量名) # 变量名存储的是具体的错误信息 else: print('如果以上代码没有发生异常以及异常处理工作就执行这里的代码') print('一般情况下else中的代码用来下结论') # logging模块 finally: print('不管代码是否有异常都会执行,且在函数中遇到return仍然会执行') print('一般情况下用于这个函数中资源的回收')
1.2 断言
assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下:
assert expression [, arguments]
assert 表达式 [, 参数]
assert len(lists) >=5,'列表元素个数小于5'
assert 2==1,'2不等于1'
备注:格式:assert 条件 , 条件为false时的错误信息 结果为raise一个AssertionError出来
# assert 条件 assert 1 == 1 assert 1 == 2
二、面向对象
概述
面向对象:核心对象二字,对象是特征与技能的结合体
基于该思想编写程序就好比是在创造一个世界,你就是这个世界的上帝,是一种上帝式的思维方式
2.1 类
面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
类:一个模型,一个图纸
类:种类、分类、类别 对象是特征与技能的结合体,类是一系列对象相似的特征与技能的结合体 强调:站的角度不同,总结出的类是截然不同的 在现实世界中:先有的一个个具体存在的对象,然后随着人类文明的发展才有了分类的概念 在程序中:必须先定义类,后调用类来产生对象 现实世界中对对象==》总结出现实世界中的类==》定义程序中的类==》调用类产生程序中的对象 站在老男孩选课系统的角度,先总结现实世界中的老男孩的学生对象(这些对象有相似的特征和技能)
对象1: 特征: 学校='oldboy' 姓名='耗哥' 年龄=18 性别='male' 技能: 选课 对象2: 特征: 学校='oldboy' 姓名='猪哥' 年龄=17 性别='male' 技能: 选课 对象3: 特征: 学校='oldboy' 姓名='帅翔' 年龄=19 性别='female' 技能: 选课 站在老男孩选课系统的角度,先总结现实世界中的老男孩学生类 老男孩学生类: 相似的特征: 学校='oldboy' 相似的技能 选课
简单例子
class Car: #定义一个类,执行类体代码 def run(self): pass def driver(self,name): #在类的名称空间产生一个函数属性的名字(技能) print("%s在开车" %name) bmw= Car() # 实例化(调用类)产生一个空对象,对象就是一个名称名称空间,就是用来存放一堆自己独有的数据属性的 #对象本质也就是一个名称空间而已,对象名称空间(容器)是用存放对象自己------独有的名字/属性,而 #类中存放的是对象们---------------------------------------------------共有的属性
定义一个连接mysql的类
import pymysql class Db: # 第一个方法-连mysql def connect(self): db_info = {', 'host': '118.24.3.40', 'db': 'jxz', 'port': 3306, 'charset': 'utf8', 'autocommit': True} self.conn = pymysql.connect(**db_info) # 建立连接 self.cur = self.conn.cursor() def excute_many(self, sql): self.cur.execute(sql) return self.cur.fetchmany() def excute_one(self, sql): self.cur.execute(sql) return self.cur.fetchone() def excute_all(self, sql): self.cur.execute(sql) return self.cur.fetchall() def close(self): self.close() self.cur.close() def export_excel(self, table_name): pass mysql = Db()
2.2 python中的self (本类对象)
首先,对于python,只有针对类来说的self才有意义,所以python中的self,说的即是python类中的self。
# class Student(object): # pass class Person: # 经典类 # 属性就是变量 # 功能就是函数 def __init__(self, uid, name): print('self的内存地址:', id(self)) self.id = uid self.name = name def cook(self): print('%s 会做鱼香肉丝' % self.name) def housework(self): print('%s 正在做家务' % self.name) xh = Person(1, '小黑') xh.housework() xb = Person(2, '小白') xb.cook()
self的内存地址: 2215143160968 小黑 正在做家务 self的内存地址: 2215143161192 小白 会做鱼香肉丝
2.3 构造函数
构造函数,类在实例化的时候会自动执行构造函数
def __init__(self):
import pymysql class Db: # 第一个方法-连mysql def __init__(self, host, user, password, db, port=3306, charset='utf8'): # 构造函数,类在实例化的时候会自动执行构造函数 self.db_info = { 'user': user, 'password': password, 'db': db, 'port': port, 'charset': charset, 'autocommit': True, 'host': host} self.connect() def check_mysql_connect(self): pass def connect(self): db_info = {', 'host': '118.24.3.40', 'db': 'jxz', 'port': 3306, 'charset': 'utf8', 'autocommit': True} self.conn = pymysql.connect(**db_info) # 建立连接 self.cur = self.conn.cursor() def excute_many(self, sql): self.cur.execute(sql) return self.cur.fetchmany() def excute_one(self, sql): self.cur.execute(sql) return self.cur.fetchone() def excute_all(self, sql): self.cur.execute(sql) return self.cur.fetchall() def close(self): self.close() self.cur.close() def export_excel(self, table_name): pass mysql = Db(', 'jxz') result = mysql.excute_one('select * from %s' % table_name)
raise Exception 发现异常时,能通过它返回具体异常提示,方便检查错误
def connect(self): try: self.conn = pymysql.connect(**self.db_info) except Exception as e: print("连接不上数据库") raise Exception("连接不上数据库,请检查连接") # raise Exception
2.3 面向对象 三大特性
封装、继承、多态
1、封装 也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
2、继承 是面向对象程序设计方法的一个重要手段,通过继承可以更有效地组织程序结构,明确类间的关系,育雏利用已有的类来完成更复杂、更深入的程序开发。
3、多态 允许以一种统一的风格处理已存在的变量和相关的类,多态性使得向系统增加功能变的容易。