day 018 面向对象--约束和异常处理
---恢复内容开始---
主要内容;
- 类的约束
- 异常处理
- 自定义异常
- MD5加密
- 日志
一 类的约束 (约束是对类的约束,)
看个例子:
这是领导分配给每个人的项目,要求每人写个功能 结果如下:
例子1
class Normal: # 张三, 普通⼈人登录
def login(self):
pass
class Member: # 李李四, 会员登录
def denglu(self):
pass
class Admin: # 王五, 管理理员登录
def login(self):
pass
现李四写的你调用不了
那么怎么处理这样的问题:
在python中有两种方法
1 提取父类,然后在父类中定义好方法,这个方法什么都不用干,就 抛一个异常就可以了,
这样所有的子类都必须重写这个方法.否则,访问就会报做
2使用元类来描述父类,在元类中给出一个抽象方法,这样子就不得不给出抽象方法的具体实现,也可以提起约束的效果
看看第一种方法: 提取一个父类,在父类中给出一个方法.并且在方法中不给出任何代码.直接抛异常:
class Base:
def login(self):
raise Exception("你没有实现login⽅方法()")
class Normal(Base):
def login(self):
pass
class Member(Base):
def denglu(self):
pass
class Admin(Base):
def login(self):
pass
# 项⽬目经理理写的总⼊入⼝口
def login(obj):
print("准备验证码.......")
obj.login()
print("进⼊入主⻚页.......")
n = Normal()
m = Member()
a = Admin()
login(n)
login(m) # 报错.
login(a)
在执行到login(m)的时候会报错,原因是此时访问的login()是父类中的方法,但父类的方法会抛出一个异常
所以会报错这样的程序就不得不写login方法了,从而对子类进行了相应的的约束.
注意 在此次 我们抛出的是Exception异常,而Exception是所有异常的根,我们无法通过这个异常来判断出程序报的什么错.
所以. 最好是换一个比较专业的错误信息. 最好
是换成NotImplementError. 其含义是. "没有实现的错误". 这样程序员或者项目经理可以⼀目
了然的知道是什么错了
第二套方案:
写抽象类和抽象⽅法. 这种方案相对来说比上一个麻烦一些. 需要给大家先
引入⼀个抽象的概念
比如. 你看看一些抽象派的画作. 在现实中是不
存在的. 也就无法建立实例对象与之相对应. 所以抽象类无法创建对象. 创建对象的时候会报
错.
在Python中编写一个抽象类比较麻烦,要引入abc模块中的ABCMeta和absstractmethod这两个内容.
from abc import ABCMeta, abstractmethod
# 类中包含了抽象方法. 那此时这个类就是个抽象类. 注意: 抽象类可以有普通方法
class IGame(metaclass=ABCMeta):
# 一个游戏到底怎么玩儿? 你能形容? 流程能一样么?
@abstractmethod
def play(self):
pass
def turn_off(self):
print("破B游戏不玩了, 脱坑了")
class DNFGame(IGame):
# ⼦类必须实现父类中的抽象方法. 否则子类也是抽象类
def play(self):
print("dnf的玩⼉儿法")
# g = IGame() # 抽象类不能创建对象
dg = DNFGame()
dg.play()
通过代码,这里的这里的IGame对DNFGame进行了约束. 换句话说. ⽗类对子类进
行了约束.
总结: 约束. 其实就是⽗类对子类进行约束. 子类必须要写xxx⽅法. 在python中约束的
方式和方法有两种:
1. 使用抽象类和抽象方法, 由于该⽅案来源是java和c#. 所以使用频率还是很少的
2. 使⽤⼈为抛出异常的⽅案. 并且尽量抛出的是NotImplementError. 这样比较专
业, 而且错误比较明确.(推荐)
二 异常处理(程序在运行过程中出现的错误)
看简单异常例子:
def chu(a, b):
return a/b
try:
ret = chu(, )
print(ret)
except Exception as e:
print('整数不能是0')
那try...except是什么意思呢? 尝试着运行xxxxx代码. 出现了错误. 就执行except后面的
代码. 在这个过程中. 当代码出现错误的时候. 系统会产生一个异常对象. 然后这个异常会向
外抛. 被except拦截. 并把接收到的异常对象赋值给e. 那这里的e就是异常对象. 那这里的
Exception是什么? Exception是所有异常的基类, 也就是异常的跟. 换句话说. 所有的错误都
是Exception的子类对象. 我们看到的ZeroDivisionError 其实就是Exception的子类. 那这样
写好像有点⼉儿问题撒. Exception表示所有的错误. 太笼统了. 所有的错误都会被认为是Exception.
当程序中出现多种错误的时候, 就不好分类了, 最好是出什么异常就⽤什么来处理. 这样就更加合理了.
所以在try...execpt语句中. 还可以写更多的except
try:
print("各种操作....")
except ZeroDivisionError as e:
print("除数不能是0")
except FileNotFoundError as e:
print("⽂件不存在")
except Exception as e:
print("其他错误")
完整的异常处语法:
try:
'''操作'''
except Exception as e:
'''异常的父类,可以捕获所有的异常'''
else:
'''保护不抛出异常的代码, 当try中⽆无异常的时候执行'''
finally:
'''最后总是要执⾏行我'''
代码. 不论处不出错. 最后都要执行finally中的语句. 一般我们用try...except就够用了. 顶多
加上finally. finally一般用来作为收尾工作.
上面是处理异常. 我们在执行代码的过程中如果出现了一些条件上的不对等. 根本不符
合我的代码逻辑. 比如. 参数. 我要求你传递一个数字. 你非得传递一个字符串. 那对不起. 我
没办法帮你处理. 那如何通知你呢? 两个方案.
方案一. 直接返回即可. 我不管你还不行么?
方案二. 抛出一个异常. 告诉你. 我不好惹. 乖乖的听话.
第一种方案是我们之前写代码经常用到的⽅方案. 但这种方案并不够好. 无法起到警示作用. 所
以. 以后的代码中如果出现了类似的问题. 直接抛一个错误出去. 那怎么抛呢? 我们要用到
raise关键字
def add(a, b):
'''
给我传递两个整数. 我帮你计算两个数的和
::param a:
::param b:
:return:
'''
if not type(a) == int and not type(b) == int:
# 当程序运⾏行行到这句句话的时候. 整个函数的调⽤用会被中断. 并向外抛出⼀个异常.
raise Exception("不是整数, 朕不不能帮你搞定这么复杂的运算.")
return a + b
# 如果调⽤方不处理异常. 那产生的错误将会继续向外抛. 最后就抛给了用户
# add("你好", "我叫赛利利亚") # 如果调用方处理了异常. 那么错误就不会丢给用户. 程序也能正常进行
try:
add("胡辣汤", "滋滋冒油的大腰子")
except Exception as e:
print("报错了. 自⼰处理去吧")
当程序运行到raise.程序就会被中断.并实例化后面的异常对象,抛给后面,如果调用方不处理,则会把错误往上跑出,最终抛给用户,如果调用方处理了异常,那程序可以正常的进行执行.
三 自定义异常( 只要你的类继承了Exception类,那你的类就是一个异常类,)
上例子: 写一个男澡堂子程序,那这时候来个女的,怎么办, 那就得抛出一个性别异常.
继承Exceptinon.那就是一个异常类
import traceback
class GenderEttor(Exception):
pass
class person:
def __init__(self,name,gender):
self.name=name
self.gender=gender
def nan_zao_tang_xi_zao(person):
if person.gender!='男':
raise GenderEttor('性别不对')
p1 =person('李四','男')
p2=person('张三','n')
nan_zao_tang_xi_zao(p2) # 报错 .会抛出一个错误 GenderError
nan_zao_tang_xi_zao((p1)) # 处理异常
try:
nan_zao_tang_xi_zao(p1)
nan_zao_tang_xi_zao(p2)
except GenderEttor as e :
val = traceback.format_exc() # 获取到堆栈信
print(e)
print(val)
except Exception as e:
print("报错")
上边 我们虽然是报错了 但是看不到错误源在哪里,想要看到那就另外引入一个模块 traceback
这个模块可以 取到我们每个地方的调用信息,
又被称为 堆栈信息
搞定了. 这样我们就能收放⾃如了. 当测试代码的时候把堆栈信息打印出来. 但是当到了
线上的生产环境的时候把这个堆栈去掉即可
四 MD5加密
在python中我们不需要⼿手写
这一套算法. 只需要引入一个叫hashlib的模块就能搞定MD5的加密工作
MD5是⼀一种不可逆的加密算法.
防止撞库 (加盐)
import hashlib
obj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf") # 加盐
obj.update("alex".encode("utf-8")) # 加密的必须是字节
miwen = obj.hexdigest()
print(miwen) # 99fca4b872fa901aac30c3e952ca786d
具体应用 注册:
注册的时候. 用md5进行加密. 存储的是加密后的密文
# username = input("请输入用户名")
# password = input("请输入密码")
# # cun = my_md5(password)
# # print(cun) # alex 26adff81aa6778d26999b95ddc0e50b2
# if username == "alex" and my_md5(password) == "26adff81aa6778d26999b95ddc0e50b2":
# print("登录成功")
# else:
# print("登录失败")
五 日志 (记录不必现BUG)
- 导入longing模块
- 简单配置下longing
- 出现异常的时候(except),向日志里写错误信息
import logging logging.basicConfig(filename='app.log', # 文件名
format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=40) # level 设置级别. 当你的信息的级别>=level的时候才会写入日志文件, 默认30 CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
# 写日志
logging.critical("我是critical")
logging.error("我是error")
logging.warning("我是警告")
logging.info("我是基本信息")
logging.debug("我是调试")
logging.log(2, "我是自定义")
import traceback
最后, 如果你系统中想要把日志⽂文件分开. 比如. 一个大项⽬, 有两个子系统, 那两个子系
统要分开记录日志. 方便调试. 那怎么办呢? 注意. 用上面的basicConfig是搞不定的. 我们要
借助⽂件助手(FileHandler), 来帮我们完成日志的分开记录
# 多文件日志处理
# 创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
# 设置日志文件内容的格式
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
logger1 = logging.Logger('A', level=40)
logger1.addHandler(file_handler)
# 记录日志
logger1.error('我是A系统') # 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
logger2 = logging.Logger('B', level=40)
logger2.addHandler(file_handler2)
# 记录日志
logger2.error('我是B系统')
多文件处理日志
day 018 面向对象--约束和异常处理的更多相关文章
- 简学Python第六章__class面向对象编程与异常处理
Python第六章__class面向对象编程与异常处理 欢迎加入Linux_Python学习群 群号:478616847 目录: 面向对象的程序设计 类和对象 封装 继承与派生 多态与多态性 特性p ...
- python 约束与异常处理
一.类的约束 1.约束就是对类的约束.其实就是父类对子类进行约束,子类必须要写xxx方法. 2.抽象:就是当我们没法对一个功能或者一个属性进行精确的表述,一般都采用抽象的方式给出. (1)抽象类的书写 ...
- pyhon基础之约束和异常处理:
约束和异常处理:内容梗概: 1. 类的约束 2. 异常处理 3. 自定义异常 4. 日志 1. 类的约束定义:约束是对类的约束常用方法:1. 提取父类.然后在父类中定义好方法.在这个方法中什么都不用干 ...
- Python面向对象(约束,异常处理,md5加密)(五)
1. 类的约束 1. 写一个父类. 父类中的某个方法要抛出一个异常 NotImplementedError class Base: def login(self): raise NotImplemen ...
- python -- 约束、异常处理、MD5
1.类的约束 1.写一个父类,父类中的某个方法要抛出一个异常 NotImplementedError class Base: # 对子类进行了约束,必须重写该方法 def login(se ...
- Python面向对象补充以及异常处理
面向对象相关内容 一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isinstance(o ...
- Python3基础(6)面向对象编程、异常处理
---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...
- day25 Pyhton学习 约束和异常处理
一.类的约束 约束是对类的约束 有两种方法: 1.提取一个父类,在父类中给出一个方法,并且在方法中不给出任何代码,直接抛异常 class Base: def login(self): raise Ex ...
- python面向对象其他相关-异常处理-反射
1.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 2.issubclass(sub, super) 检查sub类是否是 super 类的派生类 n1 = 10 ...
随机推荐
- Mysql 用户ip访问根据省份查询
表名:shop_interview_customer 表结构:customerId空为游客模式 interviedId customerId interviewIP iPdetail 1 1001 1 ...
- 【Oracle安装卸载】oracle卸载
Oracle卸载比较麻烦,不能简单卸载就完成了,有时没有卸载完整,下次安装不能很好的安装: 当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的 ...
- Daily record-June
June201. Dear, wake up! Seven o'clock now, it's time to get up. Wash your face and to have breakfast ...
- python学习 面向对象高级编程
---恢复内容开始--- 面向对象编程---oop,是一种编程思想,oop把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数 ...
- django搭建博客
https://andrew-liu.gitbooks.io/django-blog/content/index.html
- MariaDB的线程及连接
转自 linux公社 今天在这里介绍一下确认mariaDB(和MySQL一样)的链接数及线程数的方法.MariaDB和MySQL有什么不一样,现在还没有弄清楚. 这是减少数据库的负载,并能提高数据库运 ...
- mac mamp环境 和linux下 安装redis 和可视化工具 Redis Desktop Manager
mac下安装 第一步:安装redis 1. brew install redis 2.启动服务/usr/local/opt/redis/bin/redis-server 3.配置redis密码访问 编 ...
- C++构造函数和析构函数,以及构造函数特殊成员变量和函数的初始化
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 小程序之setData特殊情况 三种情况的wx:if
比如data{ “a”:{}, "b":{} } 你想完成这样的结构 //创建一个对象 var readyData={} //对象[key] =另一个对象 readyData[ke ...
- Win10安装mysql-8.0.11-winx64详细步骤
安装 mysql-8.0.11-winx64 https://blog.csdn.net/qq_20788055/article/details/80372577