本节主要内容:java
1.类的约束python
2.异常处理程序员
3.自定义异常算法
4.MD5 加密数据库
5.日志c#
一 类的约束安全
首先,你要清楚,约束是对类的越是,好比,你是一个项目经理,而后呢,你给手下的人分活,张三,你处理一下普通用户登陆,李四,你处理一下会员登陆,王五,你处理一下管理员登陆,那这个时候呢,他们就开始分别去写他们的功能了,可是呢,你要知道,程序员不必定会有那么好的默契,颇有可能三个程序员会写三个彻底不一样的方法,好比这样:ide
1 class Normal: # 张三,普通会员登陆 2 def login(self): 3 pass 4 5 class Member: # 李四,会员登陆 6 def denglu(self): 7 pass 8 9 class Admin: # 王五,管理员登陆 10 def login(self): 11 pass
而后呢,他们把代码交给你了,你看了一眼,张三和王五还算ok,这个李四写的什么鬼啊?denglu....函数
难受不??可是好歹能用,还能凑活,可是这时你这边要使用了,问题就来了测试
1 # 项目经理的入口 2 3 def login(obj): 4 print("准备验证码.....") 5 obj.login() 6 print("进入主页........")
对于张三和王五的代码,没有问题,可是李四,你是否是调用不了,那如何避免这样的问题呢?咱们要约束程序的结构,也就是说,在分配任务以前就应该把功能定义好,而后分别交给下面的程序员来完成相应的功能
在python 中有两种办法来解决这样的问题
1.提取父类,而后在父类中定义好方法,在这个方法中什么都不用干,就抛一个异常就能够了,这样全部的子类就必须重写这个方法,不然,访问的时候就会报错
2.使用元类来描述父类,在元类中给出一个抽象方法,这样子类就不得不给出抽象方法的具体实现,也能够获得约束的效果
首先,咱们先看一种解决方案,首先,提取一个父类,在父类中给出一个方法,而且在方法中不给出任何代码,直接抛异常
1 class Base: 2 def login(self): 3 raise Exception("你没有实现方法login()") 4 class Normal(Base): 5 def login(self): 6 pass 7 8 class Member(Base): 9 def denglu(self): 10 pass 11 12 class Admin(Base): 13 def login(self): 14 pass 15 16 # 项目经理的入口 17 def login(obj): 18 print("准备验证码.....") 19 obj.login() 20 print("进入主页........") 21 22 n = Normal() 23 m = Member() 24 a = Admin() 25 login(n) 26 login(m) # 报错 Exception: 你没有实现方法login() 27 login(a)
在执行 login(m)的时候程序会报错,缘由是,此时访问的 login() 是父类总的方法,可是富尅 的方法会抛出一个异常,因此报错,这样程序员就不得不写 login方法了,从而对子类进行了相应的约束
在本例中,要注意,咱们抛出的是 Exception 异常,而 Exception 是全部异常的根,咱们没法经过这个异常来判断出程序 是由于什么报的错,因此,最好是换一个 专业的错误信息,最好是换成 NotlmplementError
其含义是"没有实现的错误" 这样程序员 或者 项目经理 能够一目了然的知道是什么错了,就比如,你犯什么错了,你也不知道哪里错了,这时我告诉你,你xx 错了,你改也知道改哪不是?
第二套方案,写抽象类 和抽象方法,这种方案相对于上一种方案来讲麻烦一些,须要先引入一个抽象的概念,什么是抽象呢?这里动物的吃就是一个抽象的概念,只是一个动做的概念,没有具体实现,这就是抽象的动做,换句话说,咱们若是写一个方法,不知道方法的内部应该到底怎么写,那这个方法其实就应该是一个抽象的方法,若是一个类中包含抽象方法,那么这个类必定是一个抽象类,抽象类是不能有实例的,好比,你看看一些抽象派的画做,在现实中是不存在的,也就没法创建实例对象与之相对应,因此抽象类没法建立对象,建立对象的时候会报错.
在 python 中编写一个抽象类比较麻烦,须要 引入 abc 模块中的 ABCMeta 和 abstractmethod 这两个内容,来看一个例子
1 from abc import ABCMeta,abstractmethod 2 3 # 类中包含了抽象方法,那此时这个类就是个抽象类,注意:抽象类能够有普通方法 4 class IGame(metaclass=ABCMeta): 5 # 一个游戏到底怎么玩儿?你能形容?路程能同样么? 6 @abstractmethod 7 def play(self): 8 pass 9 10 def turn_off(self): 11 print("破游戏不玩了,脱坑了") 12 13 class DNFGame(IGame): 14 # 子类必须实现父类中的抽象方法,不然子类也是 抽象类 15 16 def play(self): 17 print("dnf 的玩儿法") 18 19 # g = IGame() # 抽象类不能建立对象 20 21 dg = DNFGame() 22 dg.play()
经过代码咱们发现这里的 IGame 对 DNFGame 进行了约束,换句话说,父类对子类进行了约束
from abc import ABCMeta,abstractmethod class Base(metaclass=ABCMeta): @abstractmethod def login(self): pass class Normal(Base): def login(self): pass class Member(Base): def denglu(self): # 这个没用了 pass def login(self): # 子类对 父类 进行 实现 pass class Admin(Base): def login(self): pass # 项目经理入口 def func(obj): print("准备验证码...") obj.login() print("进入主页.....") n = Normal() m = Member() a = Admin() func(n) func(m) func(a)
总结:约束,其实就是父类对子类进行的约束,子类必需要按照父类的要求 写 xx方法,在python中 约束的方式有两种:
1.使用抽象类和抽象方法,因为该方案来源是 java 和 c# ,因此使用频率仍是不多的
2.使用人为抛出异常的方案,而且尽可能抛出的是 NotlmplementError,这样比较专业,并且错误比较明显
二 异常处理
首先咱们说一下,什么是异常, 异常 是程序在运行过程当中产生的错误,就比如,你在回家的路上忽然天塌了,那这个属于一个异常,总之就是不正常,那若是程序出现了异常,怎么处理呢?
咱们先制造一个错误,来看看异常长什么样
def chu(a,b): return a/b ret = chu(10,0) print(ret) # 结果: # ZeroDivisionError: division by zero
什么错误呢?除法中除数不能为0,那若是真的出了这个错,你把这一对错误抛给使用者嘛? 确定不能啊
那如何处理呢???
def chu(a,b): return a/b try: ret = chu(10,0) print(ret) except Exception as e: print(e) print("除数不能为0") # 结果: # division by zero # 除数不能为0
那么 try ....except 是什么意思呢?尝试着运行 xxxx代码,出现了错误,就执行 except 后面的代码,在这个过程当中,当代码出现错误的时候,系统会产生一个异常对象,而后这个异常 会向外抛,被 except 拦截, 并把接收到的异常对象 赋值给 e,那这里的 e 就是异常对象, 那这里的 Exception 是什么呢? Exception 是全部的异常的 基类(父类) ,也就是异常的根,换句话说,全部的错误都是 Exception 的子类,那这样写 好像有点问题啊, Exception 表示全部的错误,太笼统了,全部的错误都会被认为是 Exception,当程序出 多种错误的时候,就很差分类了,组好事什么异常就用什么处理,这样就更加合理了,因此在 try...except 语句汇总,还能够写入更多的 except
try: print("各类操做...") except ZeroDivisionError as e: print("除数不能为0") except FileNotFoundError as e: print("文件不存在...") except Exception as e: print("其余错误")
此时,程序运行过程当中,若是出现了ZeroDivisionError 就会被第一个 except 捕获,若是出现了FileNotFountError 就会被第二个 except 捕获,若是都不是这链各个异常,那就会被最后的 Exception 捕获,总之最后的 Exception 就是咱们处理 异常的最后一道防卫,这是咱们 最经常使用的一套写法, 接下来看一套最完整的 异常处理写法(语法):
try: """ 操做""" except Exception as e: """ 异常的父类,能够捕获全部的异常...""" else: """保护不抛出异常的代码,当try 中 无异常的时候执行...""" finally: """最后老是要执行我...."""
解读:程序先执行操做,而后若是出错了会走 except的代码,若是不出错,这行else 中的代码,不论出不出错,最后都要执行 finally 中的 语句, 通常咱们 用 try...except 就够了,顶多加上 finally ,finally 通常用来做为收尾工做
上面是处理异常,咱们在执行代码的过程当中若是出现了一些条件上的不对等,根本不符合个人代码逻辑,好比,参数,我要求你传递一个数字,你非传递一个字符串,那 "对不起,我是 警察" 哈哈哈....... 这样的我是没办法处理的,那如何通知你呢? 两个 方案:
1.方案1: 直接返回便可,我无论你
2.方案2: 抛出一个异常,告诉你,我很差惹,乖乖的听话
第一种方案是咱们以前写代码常常用到的方案,但这种方案并不够好,没法起到警示做用,因此,之后的代码中出现了相似的问题,直接抛出一个错误,那怎么抛呢? 咱们要用到 raise 关键字
def add(a,b): """ 给我传递两个参数,我帮你计算这两个数的和 :param a: :param b: :return: """ if not type(a) == int and type(b) == int: """ 当程序运行到这句话的时候,整个函数的调用会中断,抛出一个异常""" raise Exception("不是整数,臣妾作不到啊") return a + b # 若是调用方不处理异常,那产生的错误将会继续往外抛,最后就抛给了使用者 # add("你好,我叫 张曼玉") # 若是 调用方吹了异常,那么错误就不会 抛给使用者,程序也能正常运行 try: add("我是至尊宝","你是紫霞仙子嘛?") except Exception as e: print("报错了,你本身看着办吧")
当程序运行到 raise 的时候, 程序会被中断,并实例化后面的异常对象,抛给调用方,若是调用方不处理,则会把错误继续向上抛出,最后抛给 使用者,若是调用方处理了异常,那程序能够正常运行了
说了这么多,异常也知道如何抛出 和 处理了,可是如今咱们用的都是 python 自带 的异常,若是有一天,你本身写的代码中 出现了 一个 没法用现有的 异常来解决,那怎么办? 试试,能不能 ,自定义一个??/
其实 自定义一个 也很简单,只要你的类继承 了 Exception 类,那你的类就是一个 异常类,就这么简单.
# 继承 Exception ,那这个类就是一个 异常类 class GenderError(Exception): pass class Person: def __init__(self,name,gender): self.name = name self.gender = gender def men_bathroom(person): if person.gender != "男": raise GenderError("性别不对,这里是男澡堂") p1 = Person("哈哈哥","男") p2 = Person("嘻嘻姐","我不知道") # men_bathroom(p1) # men_bathroom(p2) # 会抛出一个异常 GenderError # 处理异常 try: men_bathroom(p1) men_bathroom(p2) except GenderError as e: print(e) # 性别不对,这里是男澡堂 except Exception as e: print("反正报错了")
搞定了,可是,若是是真的报错了,咱们在测试的时候,最好是能看到错误源于哪里,怎么办呢? 须要引入一个模块, traceback,这个模块能够获取到咱们每一个方法的调用信息,有被称为堆栈信息,这个信息对咱们排错颇有帮助的
import traceback # 继承 Exception,那这个类 就是一个 异常类 class GenderError(Exception): pass class Person: def __init__(self,name,gender): self.name = name self.gender = gender def men_bathroom(person): if person.gender != "男": raise GenderError("性别不对,别进了") p1 = Person("哈哈哥","男") p2 = Person("嘻嘻姐","不知道哎") try: men_bathroom(p1) men_bathroom(p2) except GenderError as e: val = traceback.format_exc() # 获取到堆栈信息 print(e) # 性别不对,别进了 print(val) except Exception as e: print("反正错了") # 结果 # 性别不对,别进了 # raise GenderError("性别不对,别进了") # GenderError: 性别不对,别进了
搞定了,这样咱们就能收放自如了,当测试代码的时候吧 堆栈信息打印出来,可是当到了线上的生产环境的时候把这个堆栈去掉便可
四 MD5加密
想一个事情. 你在银行取钱或者办卡的时候. 咱们都要输入密码. 那这个密码若是就按照咱们输入的那样去存储. 是否是很不安全啊. 若是某一个程序员进入到了了银行的数据库. 而银行的数据库又存的都是明文(不加密的密码)密码. 这时, 整个银行的帐户里的信息都是很是不安全的. 那怎么办才安全呢? 给密码加密. 而且是不可逆的加密算法. 这样. 即便获取到了银行的帐户和密码信息. 对于黑客而言都没法进行破解. 那咱们的帐号就相对安全了了不少. 那怎么加密呢? 最多见的就是用MD5算法.
MD5是一种不可逆的加密算法. 它是可靠的. 而且安全的. 在python中咱们不须要手写
这一套算法. 只须要引入⼀个叫 hashlib 的模块就能搞定MD5的加密工做
import hashlib obj = hashlib.md5() obj.update("哈哈哥".encode("utf-8")) # 加密的必须是字节 miwen = obj.hexdigest() print(miwen) # 若是担忧被破解,也就是 撞库,能够加盐,对没错,就是 加盐 import hashlib obj = hashlib.md5(b"saddfgflhmdlfmdas") # 加盐 obj.update("alex".encode("utf-8")) miwen = obj.hexdigest() print(miwen) # 如今能够了,不会再担忧 撞库了
那 MD5 怎么用呢??
import hashlib def my_md5(s): obj = hashlib.md5() obj.update(s.encode("utf-8")) miwen = obj.hexdigest() return miwen username = input("输入用户名:") password = input("输入密码:") # 数据存储 的时候: # username:my_md5(password) # 假设如今的用户名 和 密码分别是 # hahage:b3ed7cbc208610c252e2ea825c5f31e5 # 123456:e10adc3949ba59abbe56e057f20f883e # print(my_md5(username)) # print(my_md5(password)) # 用户登陆 if my_md5(username) == "b3ed7cbc208610c252e2ea825c5f31e5" and \ my_md5(password) == "e10adc3949ba59abbe56e057f20f883e": print("成功") else: print("失败")
因此,之后存密码就不要存明文了,要存密文,安全,而且,这里的加盐不能改来改去的 ,不然,整套密码就都乱了