面向对象及异常处理
内置函数
-
总结:
__init__、__del__、__str__、attr系列、item系列、__call__
-
__str__与__repr__
- 使用print/str方法时会自动触发
__str__
方法,当__str__
不存在,尝试__repr__
- 使用repr方法时会自动触发
__repr__
方法 - repr方法通常用于返回对象的字符串表示形式
- 这两个方法都只能返回字符串
- eval方法可以将一个字符串当做有效的代码执行
- 使用print/str方法时会自动触发
-
算术运算符重载
- 示例:
class Number: def __init__(self, num): self.num = num # 对象出现在'+'左边时会自动触发 def __add__(self, other): print('__add__') return self.num + other # 对象出现在'+'右边是会自动触发 def __radd__(self, other): print('__radd__') return self.num + other # +=运算时会自动触发,没有时会触发 __add__ def __iadd__(self, other): print('__iadd__') return Number(self.num + other) n = Number(100) ret = n + 200 ret = 200 + n print(ret) n += 200 # n = n + 200 print(n)
- 自己测试
加法:__add__、__radd__、__iadd__ 减法:__sub__、__rsub__、__isub__ 乘法:__mul__、__rmul__、__imul__ 除法:__truediv__、__rtruediv__、__itruediv__ 求余:__mod、__rmod__、__imod__
-
关系运算符重载
>: __gt__ =: __ge__ <: __lt__ <=: __le__ ==: __eq__ !=: __ne__
-
示例
class Number: def __init__(self, num): self.num = num def __gt__(self, other): print('__gt__') return self.num > 200 def __lt__(self, other): print('__lt__') return self.num < other def __eq__(self, other): print('__eq__') return self.num == other # 当没有此方法时,使用!=也会触发__eq__方法 def __ne__(self, other): print('__ne__') return self.num != other n = Number(100) # print(n > 200) # print(200 > n) # print(200 == n) print(200 != n)
深浅拷贝
-
引用计数
- python中的所有变量都是对象,对象的管理采用的时引用计数的方式
- 当多一个变量指向对象计数值加1,当少一个变指向对象计数值减1,减到0是,释放对象(
__del__
)
-
函数传参
- 对于不可变的变量来说,函数中不可能改传递过来的变量
- 对于可变的容器对象及自定义对象,作为函数参数传递时,传递的是引用,可以修改该对象
-
深浅拷贝
class Person: def __del__(self): print('对象释放') p1 = Person() p2 = p1 print(id(p1)) print(id(p2)) del p1 del p2 print('OVER') def test(m): # m += 1 m[0] = 300 # n = 100 n = [100, 200] test(n) print(n) import copy lt = [1, 2, [3, 4]] # 浅拷贝,只拷贝对象本身,不拷贝对象中的元素 # lt2 = lt.copy() # 浅拷贝 lt2 = copy.copy(lt) # 深拷贝:不但拷贝对象本身,还拷贝对象中的元素 lt2 = copy.deepcopy(lt) lt[0] = 100 lt2 = 300 print(id(lt)) print(id(lt2)) print(lt) print(lt2)
数据持久化(pickle)
-
说明:数据持久化存储方案,普通文件、序列化、数据库
-
示例:
import pickle class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return 'name:{},age:{}'.format(self.name, self.age) xiaoming = Person('xiaoming', 20) # 转换为bytes类型 # s = pickle.dumps(xiaoming) # print(s) # 从字节流中提取对象 # xm = pickle.loads(s) # print(xm) # 保存到文件中 # fp = open('data.txt', 'wb') # pickle.dump(xiaoming, fp) # 从文件中获取对象 fp = open('data.txt', 'rb') xm = pickle.load(fp) print(xm)
异常处理
-
相关概念
- 错误:程序运行之前的语法问题,如:关键字、缩进、括号不成对等
- 异常:在程序运行过程中出现的问题,如:未定义变量、除数为0、属性不存在等
-
异常处理
- 说明:异常处理可以理解为特殊的流程控制语句,可以提高代码的健壮性。
-
异常语法:
try: print('正常代码') # print(a) 3/0 except Exception as e: # Exception 是所有异常的基类,此处可以捕获所有的异常 print('出现异常') print(e) print('其他内容')
-
多个异常
# 分类捕获异常 ''' try: # print(a) # 3/0 d = {} print(d['name']) except NameError as e: print('NameError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) except Exception as e: print('OtherError:', e) ''' try: # print(a) # 3/0 fp = open('123.txt') except (NameError, ZeroDivisionError) as e: # 将某些异常进行统一处理,写在一个元组中即可 print(e) except: print('其他异常')
-
完整结构(else-finally)
try: print('正常代码') print(a) except: # 出现异常时执行 print('出现异常') else: # 正常结束(没有异常)时会执行 print('正常结束') finally: # 无论有无异常,都会执行 print('最后执行')
else:正常结束时执行else中的代码
finally:无论有无异常,最后都执行
-
抛出异常:
raise
try: print('正常代码') # 根据业务逻辑的需要,手动抛出异常 raise Exception('手动抛出的异常') except Exception as e: print('异常:', e) print('OVER')
-
异常嵌套(try-except结构中再次使用try-except结构)
print('我要去上班,什么事也阻止不了我上班的脚步') try: print('我准备骑电动车') raise Exception('昨天晚上不知道哪个缺德的家伙把我充电器拔了') print('骑车提前到达公司') except Exception as e: print(e) try: print('我准备做公交车') raise Exception('等了20分钟一直没有公交车,果断放弃') print('坐公交车准时到达公司') except Exception as e: print(e) print('我准备打车') print('打车还是快,一会就到达公司') print('热情满满的开始一天的工作')
-
自定义异常类(需要继承自官方的异常基类Exception)
# 自定义异常类 class MyException(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg # 特定异常标准处理方案 def deal(self): print('处理特定的自定义异常') try: print('正常执行') # 手动抛出自定义异常 raise MyException('出现了自定义异常') except MyException as e: print(e) # 调用方法,处理异常 e.deal()
-
特殊场景
- 当我们进行文件操作时,无论过程中是否有异常,最终我们一定得进行关闭操作
- 使用with语句,可以保证文件的关闭,无论中间过程是否出现异常
# fp = open('test.txt', 'r') # 中间无论有无异常,最后一定得关闭文件 # fp.close() with open('test.txt', 'r') as fp: content = fp.read(5) print(content) # 此处不要考虑文件的关闭问题,也不用是否有异常
虚拟环境
- 为什么使用虚拟环境?
- 当一台电脑上不同软件需要依赖同一个包的不同版本时,为了进行环境隔离就出现了虚拟环境
- 安装工具:
virtualenv
pip install virtualenv
- 创建虚拟环境
virtualenv 虚拟环境目录名
- 激活虚拟环境
- 进入虚拟环境目录的
Scripts
目录 - 执行:
activate
- 进入虚拟环境目录的
- 退出虚拟环境
- 进入虚拟环境目录的
Scripts
目录 - 执行:
deactivate.bat
- 进入虚拟环境目录的
- 冷冻一个环境依赖包
- 执行:
pip freeze > requirements.txt
- 执行:
- 快速复制一个虚拟环境
- 创建一个虚拟环境
- 激活虚拟环境
- 执行:
pip install -r requirements.txt