# 类的约束:
1 # 为何要用,在哪里遇到?
2
3 # 例:贴吧登录(若不同人来写)
4 class Normal: # 张三版
5 def login(self):
6 print("普通账号登录")
7
8 class Member: # 李四版
9 def login(self):
10 print("吧务账号登录")
11
12 class Admin: # 王二版
13 def denglu(self):
14 print("管理员登陆")
15
16 项目经理
17 def login(obj):
18 obj.login()
19 #
20 n = Normal()
21 login(n)
22
23 m = Member()
24 login(m)
25
26 a = Admin()
27 login(a) # 报错 'Admin' object has no attribute 'login'
28
29 # 所以有统一调用时,要避免这样的调用不了,要约束程序的结构.也就是说.
30 # 分配任务之前就应该把功能定义好.然后分别给底下的程序员来完成相应功能
# 方法一 抛异常 (常用)
'''
提取⽗类.然后在⽗类中定义好⽅法.在这个⽅法中什么都不⽤⼲.就抛⼀个异
常就可以了.这样所有的⼦类都必须重写这个⽅法.否则.访问的时候就会报错.
(尽量抛出的是NotImplementError. 这样比较专业, ⽽且错误比较明确)
'''
1 class Base: # 项目经理 先定好规范
2 def login(self): # 强制子类做xxx事情(方法)
3 raise NotImplementedError("子类没有实现该方法") # 不做就报错 抛异常
4
5 class Normal(Base): # 张三版
6 def login(self):
7 print("普通账号登录")
8
9 class Member(Base): # 李四版
10 def login(self): # 对login方法的覆盖重写
11 print("吧务账号登录")
12
13 class Admin(Base): # 王二版
14 # def denglu(self): # 这里方法不是login就没有覆盖
15 def login(self):
16 print("管理员登陆")
17
18
19 def login(obj): # 项目经理调用
20 obj.login()
21
22 n = Normal()
23 login(n) # 当Normal (子类) 去执行login时,先回找自身,自己有所以直接执行,也就不会报错了
24
25 m = Member()
26 login(m)
27
28 # a = Admin()
29 # login(a) # 当Admin (子类) 去执行login时,会先回找自身,但他这里自己没有,所以会去父类找login,也就是执行力父类的报错
30 # 报错 NotImplementedError: 子类没有实现该方法
31
32 a = Admin()
33 login(a)
View Code
# 方案二 写抽象类和抽象⽅法 来约束子类
'''
我们如果写⼀个⽅法.不知道⽅法的内部应该到底写什么. 那这个⽅法其实就应该是⼀个抽象的⽅法.
如果⼀个类中包含抽象⽅法. 那么这个类⼀定是⼀个抽象类.抽象类是不能有实例的.如.你看看⼀些
抽象派画作.现实中是不存在的.也就⽆法建立实例对象与之相对应.所以抽象类⽆法创建对象.创时会报错
'''
1 from abc import ABCMeta,abstractmethod # 原类 抽象
2 # 贴吧登录
3 class Base(metaclass=ABCMeta): # 项目经理 抽象类
4 @abstractmethod # 抽象方法
5 def login(self): # 约束子类
6 pass
7
8 def hehe(self): # 抽象类中可以有正常方法
9 print("呵呵呵")
10
11 # b = Base() # 报错的. 原因是Base是一个抽象类. 含有抽象方法. 不允许创建对象的
12
13
14 class Normal(Base): # 张三版
15 def login(self): # 子类对抽象的内容给出具体的实现 . 重写
16 print("普通账号登录")
17
18 class Member(Base): # 李四版
19 def login(self): # 子类对抽象的内容给出具体的实现 . 重写
20 print("吧务账号登录")
21
22 class Admin(Base): # 王二版
23 # def denglu(self): # 报错 继承了前面的抽象必须覆盖
24 def login(self):
25 print("管理员登陆")
26
27
28 def login(obj): # 项目经理调用
29 obj.login()
30
31
32 n = Normal()
33 login(n)
34
35 m = Member()
36 login(m)
37
38 a = Admin()
39 login(a)
View Code
# 抽象类. 含有抽象方法. 不允许创建对象
# 一个类如果全部都是抽象方法. 这个类可以被称为接口. 用来约束子类和规范子类
# 总结
'''
当我们需要对子类进行约束:
1.抛出异常 NotImplementedError() 没有实现 -> 约定俗成. 多观察
2.写抽象类
from abc import ABCMeta, abstractmethod
class Base(metaclass = ABCMeta):
@abstractmethod
def 方法(self):
pass
如果一个类中包含了抽象方法. 那么这个类一定是一个抽象类
一个抽象类中可以包含正常的方法
接口: 接口中所有的方法都是抽象方法
子类必须重写父类中的抽象方法. 否则子类也是一个抽象类
'''
View Code
# 异常处理 try...except
# 写法(语法)
try:
'''操作'''
except '错误名称' as 别名:
'''出现错误的时候. 要干什么...'''
except '错误名称' as 别名:
'''出现错误的是偶. 要干什么'''
except Exception as e:
'''异常的父类,可以捕获所有的异常'''
else:
'''保护部抛出异常的代码,当try中无异常时执行'''
finally:
'''最后执行这里'''
'''
解读:程序先执⾏操作,然后如果出错了会走except中的代码.如果不出错,执⾏else中
的代码.不论处不出错.最后都要执⾏finally中的语句.⼀般我们⽤try...except就够⽤了.
顶多加上finally. finally⼀般⽤来作为收尾⼯作.
'''
try:
print(1/0) # 0不能做除数 ZeroDivisionError: division by zero
except ZeroDivisionError as z:
print("错了. 除数不能为0")
import traceback
# 计算a+b
def cul(a, b):
if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
return a + b
else:
# 在这里有两种方案. 1. 直接返回 , 2. 抛出异常
# raise 抛出 Exception 错误和异常,所有错误的根
raise Exception("我要的不是这个. 你应该我传递int或者float")
try:
print(cul(1,2))
print(cul(1,"疙瘩汤"))
except Exception as e:
# 获取错误信息 访问堆栈信息
print(traceback.format_exc()) # 获取堆栈信息 一般不这么写 装日志
print("有误") # 打印是给客户看的
View Code
# 日志(固定套路,用时照搬):
# 1. 导入logging模块.
# 2. 简单配置⼀下logging
# 3. 出现异常的时候(except). 向⽇志⾥写错误信息.
1 import logging
2 # filename: ⽂件名
3 # format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦
4 # 时间-名称-级别-模块: 错误信息
5 # datefmt: 时间的格式
6 # level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件
7 logging.basicConfig(filename='x1.log',
8 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
9 datefmt='%Y-%m-%d %H:%M:%S',
10 level=30)
11 # 当前配置表示 0以上的分数会被写⼊⽂件
12 # CRITICAL = 50
13 # FATAL = CRITICAL
14 # ERROR = 40
15 # WARNING = 30
16 # WARN = WARNING
17 # INFO = 20
18 # DEBUG = 10
19 # NOTSET = 0
20 logging.critical("我是critical") # 50分. 最贵的
21 logging.error("我是error") # 40分
22 logging.warning("我是warning") # 30分
23 logging.info("我是info")
24 logging.debug("我是debug")
25 logging.log(1, "我什么都不是")
View Code
1 # 例子,接上面
2 import traceback
3 try:
4 print(1/0)
5 except Exception:
6 logging.error(traceback.format_exc()) # 用法
7 print("出错了")
View Code
# 把⽇志⽂件分开 FileHandler
1 import logging
2 # 创建⼀个操作⽇志的对象logger(依赖FileHandler)
3 file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
4 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
5 logger1 = logging.Logger('A系统', level=logging.ERROR)
6 logger1.addHandler(file_handler)
7 logger1.error('我是A系统')
8
9
10 # 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
11 file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
12 file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
13 logger2 = logging.Logger('B系统', level=logging.ERROR)
14 logger2.addHandler(file_handler2)
15 logger2.error('我是B系统')