博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
day 018 面向对象--约束和异常处理
阅读量:5153 次
发布时间:2019-06-13

本文共 6461 字,大约阅读时间需要 21 分钟。

---恢复内容开始---

主要内容;

  • 类的约束
  • 异常处理
  • 自定义异常
  • MD5加密
  • 日志

一  类的约束 (约束是对类的约束,) 

 

看个例子:

这是领导分配给每个人的项目,要求每人写个功能 结果如下:

例子1

class Normal: # 张三, 普通⼈人登录    def login(self):         passclass Member: # 李李四, 会员登录    def denglu(self):        passclass Admin: # 王五, 管理理员登录    def login(self):        pass

现李四写的你调用不了

那么怎么处理这样的问题:

在python中有两种方法

1 提取父类,然后在父类中定义好方法,这个方法什么都不用干,就 抛一个异常就可以了,

这样所有的子类都必须重写这个方法.否则,访问就会报做

2使用元类来描述父类,在元类中给出一个抽象方法,这样子就不得不给出抽象方法的具体实现,也可以提起约束的效果

看看第一种方法: 提取一个父类,在父类中给出一个方法.并且在方法中不给出任何代码.直接抛异常:

class Base:    def login(self):        raise Exception("你没有实现login⽅方法()")class Normal(Base):    def login(self):        passclass Member(Base):    def denglu(self):        passclass 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)
View Code

在执行到login(m)的时候会报错,原因是此时访问的login()是父类中的方法,但父类的方法会抛出一个异常

所以会报错这样的程序就不得不写login方法了,从而对子类进行了相应的的约束.

注意 在此次 我们抛出的是Exception异常,而Exception是所有异常的根,我们无法通过这个异常来判断出程序报的什么错.  

所以. 最好是换一个比较专业的错误信息. 最好

是换成NotImplementError. 其含义是. "没有实现的错误". 这样程序员或者项目经理可以⼀目
了然的知道是什么错了

第二套方案:

写抽象类和抽象⽅法. 这种方案相对来说比上一个麻烦一些. 需要给大家先

引入⼀个抽象的概念

比如. 你看看一些抽象派的画作. 在现实中是不

存在的. 也就无法建立实例对象与之相对应. 所以抽象类无法创建对象. 创建对象的时候会报

错.

在Python中编写一个抽象类比较麻烦,要引入abc模块中的ABCMeta和absstractmethod这两个内容.

from abc import ABCMeta, abstractmethod# 类中包含了抽象方法. 那此时这个类就是个抽象类. 注意: 抽象类可以有普通方法class IGame(metaclass=ABCMeta):# 一个游戏到底怎么玩儿? 你能形容? 流程能一样么?@abstractmethoddef play(self):passdef 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/btry:    ret = chu(10, 0)    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 tracebackclass GenderEttor(Exception):    passclass person:    def __init__(self,name,gender):        self.name=name        self.gender=genderdef nan_zao_tang_xi_zao(person):    if person.gender!='男':        raise GenderEttor('性别不对')p1 =person('李四','男')p2=person('张三','n')nan_zao_tang_xi_zao(p2)  # 报错 .会抛出一个错误 GenderErrornan_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("报错")
View Code

上边 我们虽然是报错了 但是看不到错误源在哪里,想要看到那就另外引入一个模块 traceback

这个模块可以 取到我们每个地方的调用信息,

又被称为    堆栈信息

搞定了. 这样我们就能收放⾃如了. 当测试代码的时候把堆栈信息打印出来. 但是当到了

线上的生产环境的时候把这个堆栈去掉即可

 

四 MD5加密

在python中我们不需要⼿手写

这一套算法. 只需要引入一个叫hashlib的模块就能搞定MD5的加密工作

MD5是⼀一种不可逆的加密算法.

防止撞库 (加盐)

import hashlibobj = 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 logginglogging.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的时候才会写入日志文件, 默认30CRITICAL = 50FATAL = CRITICALERROR = 40WARNING = 30WARN = WARNINGINFO = 20DEBUG = 10NOTSET = 0# 写日志logging.critical("我是critical")logging.error("我是error")logging.warning("我是警告")logging.info("我是基本信息")logging.debug("我是调试")logging.log(2, "我是自定义")import traceback
View Code

最后, 如果你系统中想要把日志⽂文件分开. 比如. 一个大项⽬, 有两个子系统, 那两个子系

统要分开记录日志. 方便调试. 那怎么办呢? 注意. 用上面的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系统')
多文件处理日志

 

            

 

转载于:https://www.cnblogs.com/systemsystem/p/9726706.html

你可能感兴趣的文章
Worker Thread
查看>>
vuejs解析url地址
查看>>
nodejs服务器部署教程一
查看>>
MyEclipse 2017 CI 10 发布(附下载)
查看>>
SQL SERVER 2008筛选时报错 无法为该请求检索数据
查看>>
Oracle审计--AUD$占用空间较大处理方案
查看>>
搭建高性能计算环境(七)、应用软件的安装之MS
查看>>
ASP.NET判断是否为手机登录
查看>>
离别的回忆
查看>>
4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(远程升级WIFI内部程序)
查看>>
关于Keil4 转到 Keil5以后的一些错误解决
查看>>
推荐一个很棒的JS绘图库Flot
查看>>
uni-app,v-for时 block 和 view 的使用
查看>>
jaxp与dom4j遍历xml树
查看>>
Python字典的操作与使用
查看>>
SQL 中的连接
查看>>
老妈的教诲
查看>>
django 基础框架学习 (一)
查看>>
UML建模工具Visio、Rational Rose、PowerDesign,Visual Paradigm for UML
查看>>
HDU2191——悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
查看>>