day19 面向对象05 约束

1. 约束(1. 抛出异常, 2. 写抽象类)(难点, 重点)
  约束是对类的约束
 方法:

1. 提取父类, 抛出异常; NotImplementedError
# 贴吧
# 项目经理(级别高一点儿)
class Base:
    def login(self): # 强制子类做xxxx事
        raise NotImplementedError("子类没有实现该方法") # 报错. 抛异常

# 1. 普通账号  -->  翔哥
class Normal(Base):
    def login(self):
        print("普通账号的登录")

# 2. 吧务  - > 强哥
class Member(Base):
    def denglu(self):
        print("吧务的登录")

# 3. 百度员工  -> 明哥
class Admin(Base):
    def login(self): # 方法的覆盖和重写
        print("管理员的登录")

# 项目经理
def wodetian(obj):
    obj.login()

n = Normal()
wodetian(n)

m = Member()
wodetian(m)  # 报错
View Code
    2. 抽象类
from abc import ABCMeta, abstractmethod

class Base(metaclass = ABCMeta): 抽象类

@abstractmethod
def 方法(self):pass

class Foo(Base): 子类必须重写父类中的抽象方法
def 方法(self):
pass
# 在python中可以写出抽象类和抽象方法. 来约束子类
from abc import ABCMeta, abstractmethod
# 贴吧
# 项目经理(级别高一点儿)
class Base(metaclass=ABCMeta): # 抽象类
    # 抽象方法
    @abstractmethod # staticmethod, classmethod
    def login(self): # 强制子类做xxxx事
        pass

    def hehe(self): # 抽象类中可以有正常的方法
        print("我会呵呵呵")

# b = Base() # 报错的. 原因是Base是一个抽象类. 含有抽象方法. 不允许创建对象的

# 一个类如果全部都是抽象方法. 这个类可以被称为接口. 用来约束子类和规范子类

# 1. 普通账号  -->  翔哥
class Normal(Base):
    pass
    # def login(self): # 重写了父类中的抽象方法
    #     print("普通账号的登录")

n = Normal()  # 不重写抽象的父类方法会报错 TypeError: Can't instantiate abstract class Normal with abstract methods login
View Code
        一个类包含类抽象方法. 这个类一定是抽象类
注意: 抽象类中可以有正常类的方法

抽象类中如果有抽象方法. 这个类将不能创建对象(实例化对象)

(java和c#的概念) 接口: 类中都是抽象方法

2. 异常处理
注意: 程序员是发现不了自己的错误的, 尤其边缘性错误
完整异常处理写法
'''
try:
xxxx
except 错误名称 as 别名:
出现错误的时候. 要干什么...
except 错误名称 as 别名:
出现错误的是偶. 要干什么
....
except Exception as e: # 所有错误的根 处理异常的最后的"守门员"
出现的所有的错误. 我都可以这样处理
else: # 很少用到
不出错的时候执行这里的代码
finally:
结束. 收尾工作
'''
抛出异常: 由python解释器来调用代码, 出现了错误, 系统会自动的产生一个叫异常的对象, 系统会尝试着把错误
     返回给调用方, 这个过程成为:抛出异常
捕获异常: 通过try...except 可以把系统产生的这个错误进行捕获, 这就是捕获异常

根据对象的不同, 合理展示错误信息:
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, "胡辣汤"))
except Exception as e:
    # 获取到错误信息. 方便程序员排查, 我们需要访问堆栈信息
    print(traceback.format_exc()) # 获取堆栈信息  程序员使用
    print("出现了错误")  # 反馈给客户的错误信息
View Code

自定义异常:
class GenderException(Exception):
    pass         # 不要写任何内容

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    #  洗澡 -> 男的进男浴室
    def goto_nan_yushi(self):
        if self.gender != "":
            raise GenderException("性别不对") # 除了名字以外都是父类中的Exception
        else:
            print("欢迎光临.")
try:
    p2 = Person("wusir", "")
    p2.goto_nan_yushi()
    p1 = Person("alex", "")
    p1.goto_nan_yushi()
except GenderException as e:
    print("你去男澡堂子干嘛?")
except Exception as e:
    print("其他错误")
View Code
3. 日志处理(logging模块)
创建日志系统:
  1. 导入logging模块.
  2.
简单配置⼀下logging
  3.
出现异常的时候(except). 向⽇志⾥写错误信息
import logging
# filename: ⽂件名
# format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦
# 时间-名称-级别-模块: 错误信息
# datefmt: 时间的格式
# level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件
logging.basicConfig(filename='x1.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',  # 重点关注message
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=0) # 当前配置表示 0以上的分数会被写⼊⽂件   测试环境level设置为10, 上线一般设置为30
# CRITICAL = 50
# FATAL = CRITICAL
# ERROR = 40  # 重要
# WARNING = 30
# WARN = WARNING
# INFO = 20
# DEBUG = 10
# NOTSET = 0
logging.critical("我是critical") # 50分. 最贵的
logging.error("我是error") # 40分logging.warning("我是警告") # 警告 30
logging.info("我是基本信息") # 20
logging.debug("我是调试") # 10
logging.log(2, "我是⾃定义") # ⾃定义.日志的level级别

日志记录异常用法:
import traceback
try:
    print(1/0)  
except Exception:
    logging.error(traceback.format_exc()) 
    print("出错了")

日志文件记录信息:
  File "D:/python_workspace/day019 约束/05 日志处理.py", line 30, in <module>
    print(1/0)
ZeroDivisionError: division by zero

 
View Code


如果一个项目中, 有两个子系统, 那两个子系统要分开记录日志
import logging
# 创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler = logging.FileHandler('zuo.log', 'a', encoding='utf-8')  # open()   文件名可修改
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))

logger1 = logging.Logger('A系统', level=20)    #这里可以修改
logger1.addHandler(file_handler) # 把文件助手和日志对象绑定
logger1.error('我是A系统出错了') # 记录日志


# 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler2 = logging.FileHandler('you.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=20)
logger2.addHandler(file_handler2)
logger1.error('我是B系统出错了') # 记录日志

# 调用堆栈模块, 既可以拿到错误信息, 又不至于让用户看到错误信息
import traceback
try:
    print(1/0)
except Exception:
    logger2.critical(traceback.format_exc())
    print("出错了. 请联系管理员")

print("程序继续执行")  # 抛出错误后程序继续
View Code



原文地址:https://www.cnblogs.com/Knight-huang/p/9947799.html