前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python记录_day019 类的约束

python记录_day019 类的约束

作者头像
py3study
发布2020-01-18 11:22:22
4150
发布2020-01-18 11:22:22
举报
文章被收录于专栏:python3

一 、约束

python中约束有两种

第一种,通过抛异常进行约束,这种是子类不按我要求的来,我就给你抛异常(推荐)

操作:提取一个父类. 在父类中给出一个方法。但在方法中不给出任何代码,直接抛异常

代码语言:javascript
复制
 1  # 贴吧
 2  # 项目经理(级别高一点儿)
 3  class Base:
 4      def login(self): # 强制子类做xxxx事
 5          raise NotImplementedError("子类没有实现该方法") # 报错. 抛异常
 6 
 7  # 1. 普通账号  -->  翔哥
 8  class Normal(Base):
 9      def login(self):
10          print("普通账号的登录")
11 
12  # 2. 吧务  - > 强哥
13  class Member(Base):
14      def login(self):
15          print("吧务的登录")
16 
17  # 3. 百度员工  -> 明哥
18  class Admin(Base):
19      def denglu(self): 
20          print("管理员的登录")
21 
22  # 项目经理
23  def wodetian(obj):
24      obj.login()
25 
26  n = Normal()
27  wodetian(n)
28 
29  m = Member()
30  wodetian(m)
31 
32  a = Admin()
33  wodetian(a)   #这就会抛出异常,因为没按要求写,找不到login

异常约束

第二种,通过抽象类和抽象方法进行约束,这种是子类不按我要求的来,我就不让子类实例化

操作:提取一个父类,将父类中给出的方法定义为抽象方法,不必实现,直接pass

### 这些概念要记住:

抽象类是不能进行实例化的

如果一个类中有抽象方法,那么这个类就是抽象类

一个抽象类可以有非抽象方法

代码语言:javascript
复制
 1 from abc import ABCMeta, abstractmethod
 2 
 3 class Base(metaclass=ABCMeta): # 抽象类
 4      # 抽象方法
 5      @abstractmethod
 6      def login(self):          # 强制子类做xxxx事,子类必须重写这个方法
 7          pass
 8 
 9 class Normal(Base):
10     def login(self):
11         print("普通登录")
12 
13 class Member(Base):
14     def login(self):
15         print("会员登录")
16 
17 class Admin(Base):
18     def denglu(self):
19         print('管理员登录')
20 
21 def denglu(obj):
22     obj.login()
23 n = Normal()
24 denglu(n)
25 m = Member()
26 denglu(m)
27 a = Admin()  #Can't instantiate abstract class admin with abstract methods login
28 denglu(a)

抽象约束

二、异常处理

格式:

try:

  代码块

except  错误名 as 别名:

  出现该错误时做什么

except 错误名 as  别名:

  出现该错误时做什么

...

else:

  不出错时执行这里

finally:

  出不出错都执行这里

解读: 程序先执行操作, 然后如果出错了会走except中的代码. 如果不出错, 执行else中的代码. 不论出不出错. 最后都要执行finally中的语句. 一般我们用try...except就够了. 顶多加上finally. finally一般用来作为收尾工作。

代码语言:javascript
复制
 1 def cul(a,b):
 2     if (type(a)== int or type(a) == float) and (type(b)== int or type(b)== float):
 3         return a+b
 4     else:
 5         raise Exception("我要的是数字,你输入的是啥")
 6 
 7 try:
 8     print(cul("一",4))
 9 except Exception as e:
10     print("错了,你要输入数字")

异常处理

##抛异常

抛异常要用到关键字raise

代码语言:javascript
复制
 1 def add(a, b):
 2  '''
 3  给我传递两个整数. 我帮你计算两个数的和
 4  :param :param a:
 5  :param :param b:
 6  :return :return:
 7  '''
 8  if not type(a) == int and not type(b) == int:
 9  # 当程序运行到这句话的时候. 整个函数的调用会被中断. 并向外抛出一个异常.
10  raise Exception("不是整数, 朕不能帮你搞定这么复杂的运算.")
11  return a + b
12 # 如果调用方不处理异常. 那产生的错误将会继续向外抛. 最后就抛给了用户
13 add("你好", "我叫赛利亚")
14 # 如果调用方处理了异常. 那么错误就不会丢给用户. 程序也能正常进行
15 try:
16  add("胡辣汤", "滋滋冒油的大腰子")
17 except Exception as e:
18  print("报错了. 我要的是数字")

raise

##自定义异常

 非常简单. 只要你的类继承了Exception类. 那你的类就是一个异常类

格式:

def  异常名(Exception):

  pass

代码语言:javascript
复制
 1 #自定义异常
 2 class GenderException(Exception):
 3     pass
 4 
 5 class Person:
 6 
 7     def __init__(self,name,gender):
 8         self.name = name
 9         self.gender = gender
10 
11     def goto_nan(self):
12         if self.gender !="男":
13             raise GenderException("性别不对")
14         else:
15             print("欢迎光临")
16 try:
17     p1 = Person('alex', '男')
18     p1.goto_nan()
19 
20     p2 = Person('妖姬', '女')
21     p2.goto_nan()
22 
23 except GenderException as e:
24     print("你来错地儿了")
25 except Exception as e:
26     print("其他错误")

自定义异常

##异常处理好是好,但是有一个问题,我们在调试的时候是希望看到程序哪里出现问题的,而异常处理没有具体的错误信息,那这么办呢?这时需要引入另一个模块traceback. 这个模块可以获取到我们每个方法的调用信息. 又被称为堆栈信息. 这个信息对我们排错是很有帮助的.

代码语言:javascript
复制
 1 import traceback
 2 
 3 # 继承Exception. 那这个类就是一个异常类  自定义异常
 4 class GenderError(Exception):
 5      pass
 6 class Person:
 7      def __init__(self, name, gender):
 8          self.name = name
 9          self.gender = gender
10 
11 def nan_zao_tang_xi_zao(person):
12      if person.gender != "男":
13          raise GenderError("性别不对. 这里是男澡堂子")
14 
15 p1 = Person("alex", "男")
16 p2 = Person("eggon", "蛋")
17 # nan_zao_tang_xi_zao(p1)
18 # nan_zao_tang_xi_zao(p2) # 报错. 会抛出一个异常: GenderError
19 
20 # 处理异常
21 try:
22      nan_zao_tang_xi_zao(p1)
23      nan_zao_tang_xi_zao(p2)
24 except GenderError as e:
25      val = traceback.format_exc() # 获取到堆栈信息
26      print(e) # 性别不对. 这里是男澡堂子
27      print(val)
28 except Exception as e:
29      print("反正报错了")        
30 结果:
31 性别不对. 这里是男澡堂子
32 Traceback (most recent call last):
33  File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 155, in
34 <module>
35      nan_zao_tang_xi_zao(p2)
36  File "/Users/sylar/PycharmProjects/oldboy/面向对象/day05.py", line 144, in
37 nan_zao_tang_xi_zao
38      raise GenderError("性别不对. 这里是男澡堂子")
39 GenderError: 性别不对. 这里是男澡堂子

View Code

这样我们就能收放放如了. 当测试代码的时候把堆栈信息打印出来. 但是当到了 线上的生产环境的时候把这个堆栈去掉即可

三、日志(不用记,知道怎么用就行)

当出现任何错误的时候. 我们都可以去日志系统里去查. 看哪里出了问题. 这样在解决问题和bug的时候就多了一个帮手。

那如何在python中创建这个日志系统呢? 

1. 导入logging模块.

2. 简单配置一下logging

3. 出现异常的时候(except). 向日志里写错误信息.

代码语言:javascript
复制
 1 #参数解释
 2 # filename: 文件名
 3 # format: 数据的格式化输出. 最终在日志文件中的样子
 4 # 时间-名称-级别-模块: 错误信息
 5 # datefmt: 时间的格式
 6 # level: 错误的级别权重, 当错误的级别权重大于等于leval的时候才会写入文件
 7 
 8 import logging  #导入模块
 9 #简单配置,一般只需修改level值
10 logging.basicConfig(filename='x1.txt',
11  format='%(asctime)s - %(name)s - %(levelname)s -%
12 (module)s: %(message)s',
13  datefmt='%Y-%m-%d %H:%M:%S',
14 level=0) # 当前配置表示 0以上的分数会被写入文件
15 # CRITICAL = 50
16 # FATAL = CRITICAL
17 # ERROR = 40
18 # WARNING = 30
19 # WARN = WARNING
20 # INFO = 20
21 # DEBUG = 10
22 # NOTSET = 0
23 logging.critical("我是critical") # 写入critical级别信息
24 logging.error("我是error") # 写入error级别信息
25 logging.warning("我是警告") # 警告 
26 logging.info("我是基本信息") # 
27 logging.debug("我是调试")  
28 logging.log(2, "我是自定义") # 自定义.  第一个参数可以自己给值,第二个是往日志文件里写的内容
代码语言:javascript
复制
 1  1 import logging
 2  2 
 3  3 logging.basicConfig(filename='x1.log',
 4  4      format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
 5  5      datefmt='%Y-%m-%d %H:%M:%S',
 6  6     level=35)  # 当前配置表示 35以上的级别会被写入文件
 7  7 
 8  8 import traceback
 9  9 try:
10 10     print(1/0)
11 11 except Exception:
12 12     logging.error(traceback.format_exc()) # 写入error信息
13 13     logging.log(36, traceback.format_exc())  # 自定义写入
14 14     print("出错了")
15 15 结果:
16 16 x1.txt内容
17 17 
18 18 2018-11-12 20:43:01 - root - ERROR -日志系统: Traceback (most recent call last):
19 19   File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
20 20     print(1/0)
21 21 ZeroDivisionError: division by zero
22 22 
23 23 2018-11-12 20:43:01 - root - Level 36 -日志系统: Traceback (most recent call last):
24 24   File "D:/PyCharm/workspace/day019 约束/日志系统.py", line 29, in <module>
25 25     print(1/0)
26 26 ZeroDivisionError: division by zero

日志应用

##

最后, 如果你系统中想要把日志文件分开. 比如. 有个大项目, 有两个子系统, 那两个子系 统要分开记录日志. 方便调试. 那怎么办呢? 注意. 用上面的basicConfig是搞不定的. 我们要借助文件助手(FileHandler), 来帮我们完成日志的分开记录

代码语言:javascript
复制
 1 import logging
 2 
 3 # 创建一个操作日志的对象logger(依赖FileHandler)
 4 file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
 5 file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))
 6 
 7 logger1 = logging.Logger('a系统', level=logging.ERROR)  #级别
 8 logger1.addHandler(file_handler)   #把文件助手和日志对象绑定
 9 logger1.error('我是A系统')   #写入日志信息
10 
11 # 再创建一个操作日志的对象logger(依赖FileHandler)
12 file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
13 file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
14 
15 logger2 = logging.Logger('b系统', level=logging.ERROR)  #级别
16 logger2.addHandler(file_handler2)
17 logger2.error('我是B系统')  #写入日志信息

日志分开

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/04/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档