一、类的约束

真正写写项目的代码时都是多人协作的,所以有些地方需要约束程序的结构。也就是说,在分配任务之前就应该把功能定义好,然后分别交给底下的程序员来完成相应的功能。

在python中有两种办法来约束类的方法:

  • 第一种方法使用继承的特性:提取⽗类,然后在⽗类中定义好⽅法,在这个⽅法中什么都不⽤⼲,就抛⼀个异常就可以了。这样所有的⼦类都必须重写这个⽅法,否则访问的时候就会报错。
class Base:
def run(self):
raise NotImplementedError('子类没有实现login方法') class Foo1(Base):
def run(self):
print('Foo1\'s Function') class Foo2(Base):
def run(self):
print('Foo2\'s Function') class Foo3(Base):
def run3(self): # Foo3中没有按规范重写run方法,这里会报错
print('Foo3\'s Function') l1 = [Foo1(), Foo2(), Foo3()]
for item in l1:
item.run()

结果如下:

  • 第二种方法是使⽤元类来描述⽗类:在元类中给出⼀个抽象⽅法,这样⼦类就不得不给出抽象⽅法的具体实现,也可以起到约束的效果。
from abc import ABCMeta, abstractmethod                 # 导入抽象元类和定义抽象方法的装饰器

class Aminal(metaclass=ABCMeta):                        # 在创建类的时候指定要使用ABCMeta元类
@abstractmethod
def eat(self): # 然后定义了一个抽象方法
pass class Cat(Aminal):
pass c = Cat()
c.eat()

上面的结果告诉我们,必须要实现抽象类才能实例化这个对象,手动重写这个方法后就能正常使用了:

from abc import ABCMeta, abstractmethod

class Aminal(metaclass=ABCMeta):
@abstractmethod
def eat(self):
pass class Cat(Aminal):
def eat(self):
print('猫抓老鼠') c = Cat()
c.eat() # 结果:
# 猫抓老鼠

总结: 约束. 其实就是⽗类对⼦类进⾏约束. ⼦类必须要写xxx⽅法. 在python中约束的⽅式和⽅法有两种:

  • 使⽤抽象类和抽象⽅法, 由于该⽅案来源是java和c#. 所以使⽤频率还是很少的
  • 使⽤⼈为抛出异常的⽅案. 并且尽量抛出的是NotImplementError. 这样比较专业, ⽽且错误比较明确.(推荐)

二、异常处理:

异常:所谓异常就是程序在运行过程中出现的异常,这种是事先不能预知的,只有在程序运行时才会出现,所以我们要编写异常处理的程序来应对。

try:
坑能抛出异常的语句 except 异常1:
捕获异常1时处理的步骤 except 异常2:
捕获异常2时处理的步骤 finally:
try语句块最后执行的操作

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

我们先来看个异常的例子:

# 计算a+b

def cal(a, b):
try:
return a + b
except TypeError as v: # 捕获到TypeError异常时执行这段代码块的处理步骤
print('输入正确的数字(整数或者小数)') cal(10, '胡辣汤') # 这个时候会执行自定义的处理方法
# 输入正确的数字(整数或者小数)

上面我们捕获到异常都是python自定义的异常(TypeErrorExcept等),在一些特定的场景中可能python内置的异常种类不能全部适用,所以我们需要抛出自定义的异常。那么自定义的异常要怎么写?⾃定义异常: 非常简单,只要你的类继承了Exception类,那你的类就是⼀个异常类,就这么简单。

class MyException(Exception):                   # 类继承了Exception类,这个类就是⼀个异常类了
pass def cal(a, b):
if ((type(a) == int) or type(a) == float) and ((type(b) == int) or type(b) == float):
return a + b
else:
raise MyException('输入正确的数字(整数或者小数)') # 当判断条件为假时我们手动抛出这个自定义异常 try:
cal(10, '胡辣汤')
except MyException as m: # 然后这里捕获异常
print('捕捉到自定义的异常') # 捕获到异常后执行具体的处理步骤 except Exception as e: # Exception可以放在最后面,可以捕获所有异常
print('出错了')
finally:
print('计算完成') # 最后finally语句结尾 # 执行结果:
# 捕捉到自定义的异常
# 计算完成

这里再介绍一个知识点:查看具体的错误信息,当我们真正在调试的时候,最好是能看到错误源⾃于哪⾥,怎么办呢?需要引入另⼀个模块traceback这个模块可以获到我们每个⽅法的调⽤信息,⼜被成为堆栈信息,这个信息对我们拍错是很有帮助的,使用方法如下:

import traceback
def cal(a, b):
try:
return a + b
except TypeError as v:
print(traceback.format_exc()) # 这里可以把错误的堆栈信息打印出来,可以方便调试 cal(10, '胡辣汤')

三、MD5加密

MD5消息摘要算法(MD5 Message-Digest Algorithm)是⼀种不可逆的加密算法,它是可靠的,并且安全的(关于MD5加密这一块这里不多做介绍,后面会另外写博客介绍加密/解密这一块的)。在python中我们不需要⼿写这⼀套算法,只需要引入⼀个叫hashlib的模块就能搞定MD5的加密⼯作:

import hashlib

obj = hashlib.md5()                 # 返回一额hash对象
obj.update("alex".encode("utf-8")) # 加密的必须是字节
miwen = obj.hexdigest()
print(miwen) # 534b44a19bf18d20b71ecc4eb77c572f

这样加密一串字符真的安全吗,我们在网上有很多在线解密MD5的工具,这个这个字符串放到那些网站上一解密就出来了,如下图:

那么这是为什么呢,这是因为MD5存在的历史悠久,很多字符已经被加密记录到一个库中了,这种所谓的解密就是再这个库中查找记录,如果找到了就成为解密成功,那我们应该怎么避免这种问题呢,其实很简单,我们在生成hash对象时加点盐(salt)就OK了:

import hashlib

obj = hashlib.md5(b'sjfqwjbekwjbckwo23o920fl2')
obj.update("alex".encode("utf-8"))
miwen = obj.hexdigest()
print(miwen) # 19c7d5410eda9452205f6b59e8ba2c33
# 这时候在拿去解密他就解密不了了

四、日志(logging模块)

logging模块的使用方法:

  • 导入logging模块
  • 简单配置⼀下logging
  • 出现异常的时候(except). 向⽇志⾥写错误信息.

logging模块的简单使用:

# filename: ⽂件名
# format: 数据的格式化输出. 最终在⽇志⽂件中的样⼦
# 时间-名称-级别-模块: 错误信息
# datefmt: 时间的格式
# level: 错误的级别权重, 当错误的级别权重⼤于等于leval的时候才会写⼊⽂件
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) # 当前配置表示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, "我是⾃定义") # ⾃定义. 看着给分

最后, 如果你系统中想要把⽇志⽂件分开,比如,⼀个⼤项⽬,有两个⼦系统,那两个⼦系统要分开记录⽇志,⽅便调试,那怎么办呢?注意,⽤上⾯的basicConfig是搞不定的,我们要借助⽂件助⼿(FileHandler),来帮我们完成⽇志的分开记录;这里如果要修改日志的文件编码格式也是在这里改的:

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('我是A系统') # 再创建⼀个操作⽇志的对象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('我是B系统')

python学习笔记:第19天 类的约束、异常、MD5和logging的更多相关文章

  1. Python学习笔记(一)类和继承的使用

    一年前就打算学Python了,折腾来折腾去也一直没有用熟练,主要是类那一块不熟,昨天用Python写了几个网络编程的示例,感觉一下子迈进了很多.这几天把学习Python的笔记整理一下,内容尽量简洁. ...

  2. Python学习笔记:面向对象(类)

    1.类定义:Python3中,如果新建的类没有继承任何其他类,默认继承基础类object.Python2中如果没有显式继承object类就是经典类,而显式继承了object类就是新式类,Python2 ...

  3. Python学习笔记(六)——类和对象

    1.self的用法 全面理解self 2. 继承 子类继承父类,自动拥有父类的全部方法 >>> class Animal: def run(self): print('Animal ...

  4. python学习笔记(24)-类与对象

    #类与对象 #python类的语法 关键字 class #class 类名 类名的规范是:数字字母下划线组成,不能以数字开头 首字母大写 驼峰命名 #类属性 放在类里面的变量值 #类方法 放在类里面的 ...

  5. python学习笔记(五)---函数与类

    函数 def为定义函数的一个标志 demo1: def greet_user(username): print("Hello, " + username.title() + &qu ...

  6. python学习笔记1 -- 面向对象编程类和实例

    由于之前有一定基础,所以python中的类的概接受的比较快,与其他语言一样, python也是通过类来进行事务的抽象,一切皆对象,要不然怎么说程序员不缺对象呢. 言归正传,python中类的声明是cl ...

  7. python学习笔记(19)--PTVS的安装

    说明: 1. 折腾了两天eclipse,pydev,好不容易都弄好了,发现不会建工程,建完工程打不开,老是提示工作空间里有隐藏文件什么的,网上查了说是把.project里面的name标签的名字改了就行 ...

  8. python学习笔记十二:类的定义

    demo #!/usr/bin/python class Person: name = 'jim' age = 25 def say(self): print 'My name is ' + self ...

  9. Python学习笔记之unittest测试类

    11-3 雇员:编写一个名为Employee 的类,其方法__init__()接受名.姓和年薪,并将它们都存储在属性中.编写一个名为give_raise()的方法,它默认将年薪增加5000美元,但也能 ...

  10. python学习笔记(19)-切片

    转自https://www.jianshu.com/p/15715d6f4dad 在利用python解决各种实际问题的过程中,经常会遇到从某个对象中抽取部分值的情况,切片操作正是专门用于完成这一操作的 ...

随机推荐

  1. MacOS上好用的软件

    持续补充中…… 记录一些除了MacOS(Sierra)自带工具外,其他好用的软件. 截屏软件 Jietu——在AppStore中查找“Jietu”就可以找到这款软件.这是腾讯出品的一款用于MacOS系 ...

  2. 推荐一个可以把网页背景色调成护眼色的Chrome扩展应用

    程序员一天有10几个小时要面对着电脑,老是这种白晃晃的屏幕,谁的眼睛受得了? 我在网上逛了一圈,找到一个比较实用的Chrome扩展应用,可以一键实现将Chrome打开网页的背景色修改成护眼的豆沙绿,这 ...

  3. Linux(十一) 文件目录权限 chmod umask chown

    一 文件目录权限定义 首先我们先认识一下文件目录的权限定义,请看下面ls -l的结果我们发现一个文件或者目录的前面有10位的信息,第一位表示文件类型,大概有一下几种类型:d 表示目录 - 普通文件 b ...

  4. Mac OS系统下配置hosts的方法

    首先,介绍下什么是hosts Hosts是一个没有扩展名的系统文件,可以用系统自带的记事本等工具打开,作用就是将一些常用的网址域名与其对应的IP地址建立一个关联,当用户在浏览器输入一个需要登录的网址时 ...

  5. jquery基础介绍-转

    学习目的:理解 Ajax 及其工作原理,构建网站的一种有效方法. Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写. 下面是 Ajax 应用程 ...

  6. oracle 通配符及regexp_count函数说明

    通配符 通配符描述示例      %:匹配包含零个或更多字符的任意字符串.WHERE title LIKE '%computer%' 将查找处于书名任意位置的包含单词 computer 的所有书名.  ...

  7. python-正则基础

    正则表达式,说的简单些,就是一个匹配的功能,在python中,只要引用 re 模块,就能进行正则匹配操作 一.math匹配 先来看一个简单的例子 import re re.match(pattern, ...

  8. C# 控制台模拟序列化和反序列化

    序列化:将对象转换成二进制串的过程 反序列化:将序列化过程中产生的二进制串转换成对象的过程 作用:传输数据 using System; namespace WriteTextContent { [Se ...

  9. idea删除module

    先remove , 再点击delete

  10. 课时53.video标签第二种格式(掌握)

    由于视频数据非常非常的重要,所以五大浏览器厂商都不愿意支持别人都视频格式,所以导致了没有一种视频格式是所有浏览器都支持的,这个时候W3C为了解决这个问题,所以推出了第二种video标签的格式 如何查看 ...