一 . 约束
约束: 约束其派生类,保证派生类(子类)中必须编写指定的方法,不然执行可能就会报错.
****在python 中,约束的方法:
------- 人为主动抛出异常
-------- 抽象类 + 抽象方法
1 .语法 : ----人为抛出异常
class BaseMessage(object): """ 必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑. """ def send(self,x1): raise NotImplemented("send(),必须被重写") # raise Exception(".send()必须被重写")---不建议怎么写,不专业 class Foo(BaseMessage): def send(self,x1): """ 必须继承BaseMessage,然后其中必须编写send方法。用于完成具体业务逻辑. """ pass obj = Foo() obj.send(1)
2. 语法----抽象类 + 抽象方法
from abc import ABCMeta,abstractmethod #必须语法 class Base(metaclass=ABCMeta): # 抽象类 def f1(self): print(123) @abstractmethod def f2(self): # 抽象方法 pass class Foo(Base): def f2(self): print(666) obj = Foo() obj.f1()
课外小补充 -----Java C#
#在 Java 和 C# 中,可以实现约束的方法有--人为抛出异常/抽象类/接口 ######抽象类 + 抽象方法 #抽象类,约束继承他的派生类必须实现它其中的抽象方法 abstact class Foo: def f1(self): print(1, 3, 4) abstact def f2(self): pass class Bar(Foo): def f2(self): print('111') ########接口 #接口不允许在方法内部写代码,只能约束继承它的类必须实现接口中定义的所有方法. interface IFoo: def f1(self, x1): pass #不允许写代码 def f2(self, x1): pass interface IBar: def f3(self, x1): pass #不允许写代码 def f4(self, x1): pass class Foo(IFoo, IBar): # 实现了2个接口 def f1(self, x1): pass def f2(self, x1): pass def f3(self, x1): pass def f4(self, x1): pass
总结:
1.接口 :
---- 接口是一种数据类型 ,主要用于约束派生类中必须实现指定的方法.
--- python中是不存在接口的, Java 和 C# 中存在.
2.python 中用来实现约束的方法:
---- 抽象类 + 抽象方法 (编写上相比麻烦)
---- 人为主动抛出异常
3. 约束时 ,抛出的异常:
---- raise NotImplementedError(".send()必须被重写.")
---- raise Exception(".send()必须被重写.") -------不专业
4. 应用场景 :
---- 多个类,内部都必须有某些方法时 ,需要使用 基类 + 异常 进行约束(比如学生管理系统)
二 . 加密 hashlib
在很多的程序中,都是要用户去输入用户名和密码的,当接受到这些信息的时候,会存到数据库中,但是当我们如果是用户怎么输入我们怎么保存会出现如果数据库泄露,那么会造成很大损失.所有,这个时候我们要给 密码加密,将密文存到文件中.
注意 : 密文是不可反解的
#导入hashlib模块 import hashlib # 实例化对象 obj = hashlib.md5() # 写入要加密的字节 obj.update("asdfg".encode('utf-8')) #加密的时候要求以字节的形式,所有要转换成字节 # 获取密文 v = obj.hexdigest() print(v) 结果: 040b7cf4a55014e185813e0644502ea9
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,也就有了--"加盐"
import hashlib # 实例化对象 obj = hashlib.md5(b"258aegh") #设置一个自己的特殊词语,使和别人的不同,更保密 # 写入要加密的字节 obj.update("admin".encode('utf-8')) # 获取密文 v = obj.hexdigest() print(v) 结果: 21232f297a57a5a743894a0e4a801fc3 #未加盐之前的 admin 9a0fd7c40dd8f2202e221f08ece6e264 #加盐之后的
import hashlib SALT = b'2erer3asdfwerxdf34sdfsdfs90' def md5(pwd): # 实例化对象 obj = hashlib.md5(SALT) # 写入要加密的字节 obj.update(pwd.encode('utf-8')) # 获取密文 return obj.hexdigest() #在检查的时候要先给用户输入的密码加密在比较 user = input("请输入用户名:") pwd = input("请输入密码:") if user == 'oldboy' and md5(pwd) == 'c5395258d82599e5f1bec3be1e4dea4a': print('登录成功') else: print('登录失败')
三 . logging 模块
用于便捷记录日志且线程安全的模块
1. 单文件日志
import logging logging.basicConfig(filename='log.log', #路径,没有明确路径就在本层目录平级创建目录 #站位 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', #时间, level=10) #当前写的等级(自己定的) logging.debug('debug') #日志等级 logging.info('info') logging.warning('warning') logging.error('error') logging.critical('critical')
日志等级 CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
注意:只有[当前写的等级] 大于或等于 [日志等级] 的时候日志是会才会被记录.
import logging logger = logging.basicConfig(filename='xxxxxxx.txt', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=30) logging.debug('x1') # 10 logging.info('x2') # 20 logging.warning('x3') # 30 logging.error('x4') # 40 logging.critical('x5') # 50 import traceback def func(): try: a = a +1 #错误代码 except Exception as e: # 获取当前错误的堆栈信息 msg = traceback.format_exc() logging.error(msg) func()
###########记录到日志的错误类型 2018-08-31 19:30:56 - root - WARNING -10.日志: x3 2018-08-31 19:30:56 - root - ERROR -10.日志: x4 2018-08-31 19:30:56 - root - CRITICAL -10.日志: x5 ########记录到日志中的具体错误 2018-08-31 19:30:56 - root - ERROR -10.日志: Traceback (most recent call last): File "E:/飞Q/s15day26/课上代码/s15day26课上所有/10.日志.py", line 22, in func a = a +1 UnboundLocalError: local variable 'a' referenced before assignment
2. 多文件日志
对于上述记录日志的功能,只能将日志记录到单文件中,想要设置多个文件记录不同日志,logging.basicConfig 将无法完成 ,需要自定义文件和日志操作对象.
# 定义文件 file_2_1 = logging.FileHandler('l2_1.log', 'a') fmt = logging.Formatter() file_2_1.setFormatter(fmt) # 定义日志 logger2 = logging.Logger('s2', level=logging.INFO) logger2.addHandler(file_2_1)
import logging # 创建一个操作日志的对象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('s1', level=logging.ERROR) logger1.addHandler(file_handler) #写日志 logger1.error('123123123') # 在创建一个操作日志的对象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('s2', level=logging.ERROR) logger2.addHandler(file_handler2) logger2.error('666')
注意: 错误写法
import logging logger1 = logging.basicConfig(filename='x1.txt', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=30) logging1.error('x4') logger2 = logging.basicConfig(filename='x2.txt', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=30) logging2.error('x5') ######这样写2个日志都写入 x1.txt 文件中.因为在内存中 x1.txt 先创建,如果在新建立一个将无法代替
四 . 自定义异常
自定义异常:
# 知识点:如何自定义异常类? class MyException(Exception): def __init__(self,code,msg): self.code = code self.msg = msg try: # 知识点:主动抛出异常 (raise 实例化异常对象 ) raise MyException(1000,'操作异常') except KeyError as obj: print(obj,1111) except MyException as obj: # 知识点:捕获异常 print(obj,2222) except Exception as obj: print(obj,3333)
业务逻辑复杂的,代码多的可以用自定义异常,发生的异常自己可以知道是什么异常.
定义自定义异常类的准则--继承 Exception(所有异常类的基类).
import os class ExistsError(Exception): pass class KeyInvalidError(Exception): pass def new_func(path,prev): """ 去path路径的文件中,找到前缀为prev的一行数据,获取数据并返回给调用者。 1000,成功 1001,文件不存在 1002,关键字为空 1003,未知错误 ... :return: """ response = {'code':1000,'data':None} try: if not os.path.exists(path): raise ExistsError() if not prev: raise KeyInvalidError() pass #往下走自己逻辑 except ExistsError as e: #捕获异常 response['code'] = 1001 response['data'] = '文件不存在' except KeyInvalidError as e: response['code'] = 1002 response['data'] = '关键字为空' except Exception as e: response['code'] = 1003 response['data'] = '未知错误' return response