python keyerror_盘一盘 Python中的各种错误类型

↑↑↑关注后"星标"简说Python

人人都可以简单入门Python、爬虫、数据分析  简说Python严选 

来源:王的机器    作者:王圣元

One old watch, like brief python

c3671bb20e3f4fbc1489f6baee215b04.png

0引言

用 Python 写代码的流程(flow)可类比成三种演绎故事的形式,按顺序写、按条件写(if)、重复写(while, for),这些都叫做流程控制(control flow)。

  • 按顺序:一句一句写

  • 按条件:用 if 语句

  • 按重复:

    • 用 for 循环 - 当循环次数事先知道

    • 用 while 循环 - 当循环次数事先不知道

前提是代码运行不出错。如果出错了需要异常处理(exception handling)。处理异常或错误我们首先要知道它们的类型,才能有的放矢。这就是本贴的内容

本帖的内容如下:

  1. 从高层面了解三大错误类型

  2. 从具体层面了解常见错误类型

  3. 用面向对象编程的期权定价例子来说明

1三类错误

程序中的错误(error)又称 bug,可以分为三大类:

  1. 语法错误(syntax error)

  2. 运行错误(runtime error)

  3. 逻辑错误(logical error)

先看下图的总结。

32cbb7a027af389e496b953e2691aa1d.png

语法错误

语法错误顾名思义就是没有遵循 Python 语言的语法,在程序编译(compliation)时报错,而且容易识别。语法错误的常见例子有:

  • 关键词拼错:print 打成 primt

  • 函数最后没带冒号:def fun()

  • 字符串最后没带引号:'error

  • 括号不匹配:print(

  • 缩进位置错误

等等。

分析上图具体的中文和 Python 代码的语法错误例子:

# 中文昨天,送给我几本书。# Python 代码print('I love you)
  • 那句中文缺少主语。

  • 那句代码字符串没有引号。

运行错误

运行错误顾名思义是在程序运行时报错,不太容易识别。因为有些错误真的是你不运行根本不知道这里会出错,除非你过去有丰富的经验。运行错误的常见例子有:

  • 分母为零

  • 整数加字符串

  • 使用没有定义的变量名

  • 调用没有定义的函数

  • 读取不存在的文件

等等。

分析上图具体的中文和 Python 代码的运行错误例子:

# 中文我飞到月球去看风景。# Python 代码a = 10b = 0c = a/b
  • 那句中文中的“我飞到月球去看风景”这句话没有语法错误,但是实操时根本不可行。

  • 那句代码在做除法时中分母为零。

逻辑错误

逻辑错误在程序运行时根本不报错,只是产出不是想要的结果,因此很难识别。逻辑错误的常见例子有:

  • 用错变量名

  • 缩进错了整块代码

  • 用错操作符优先级

  • 用错布尔表达式

等等。

分析上图具体的中文和 Python 代码的逻辑错误例子:

# 中文因为我满仓入市,所以股市一定涨。# Python 代码(a, b) = (10, 8)print('The mean of a and b is', a+b/2)
  • 那句中文虽然没任何语法错误,也可能发生(运气好赌对了),但是毫无逻辑。

  • 那句代码想求 a 和 b 的均值,应该写成 (a+b)/2 但是写成 a+b/2。

2具体错误

由下图所示,程序开始时有两种可能,1. 没报错,2. 报错。没报错时程序按照顺序、按照条件语句(if),按照循环语句(for, while)跑,如果报错了 Python 会给你很详细的信息。

8664a985389e576fc8936338690d092b.png

下表是最齐全的错误层级表,每个错误类型都是 BaseException 的子类,而我们一般讲的异常处理是 Exception 下面的子类。

接下来我们就来看看常见的错误类型(下表粉色)。

BaseException+-- SystemExit+-- KeyboardInterrupt+-- GeneratorExit+-- Exception+-- StopIteration
+-- ArithmeticError | +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError+-- AssertionError+-- AttributeError+-- BufferError+-- EOFError+-- ImportError
+-- LookupError
| +-- IndexError
| +-- KeyError+-- MemoryError+-- NameError
| +-- UnboundLocalError+-- OSError| +-- BlockingIOError| +-- ChildProcessError| +-- ConnectionError| | +-- BrokenPipeError| | +-- ConnectionAbortedError| | +-- ConnectionRefusedError| | +-- ConnectionResetError| +-- FileExistsError| +-- FileNotFoundError| +-- InterruptedError| +-- IsADirectoryError| +-- NotADirectoryError| +-- PermissionError| +-- ProcessLookupError| +-- TimeoutError+-- ReferenceError+-- RuntimeError| +-- NotImplementedError+-- SyntaxError
| +-- IndentationError| +-- TabError+-- SystemError+-- TypeError
+-- ValueError| +-- UnicodeError| +-- UnicodeDecodeError| +-- UnicodeEncodeError| +-- UnicodeTranslateError+-- Warning+-- DeprecationWarning+-- PendingDeprecationWarning+-- RuntimeWarning+-- SyntaxWarning+-- UserWarning+-- FutureWarning+-- ImportWarning+-- UnicodeWarning+-- BytesWarning+-- ResourceWarning

由于代码太过于简单,几乎不需要额外解释。

SyntaxError SyntaxError
print('字符串最后没有单引号)
File "", line 1
    print('函数最后没有小括号'
                     ^
SyntaxError: unexpected EOF while parsing
print('函数最后没有小括号'
File "", line 1
    print('函数最后没有小括号'
                     ^
SyntaxError: unexpected EOF while parsing
IndentationError

作为 SyntaxError 的子类,当缩进有问题时报错。

if True:print('缩进有问题')
File "", line 2
    print('缩进有问题')
        ^
IndentationError: expected an indented block
NameError NameError
not_defined
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
input-19-f59b2fe187d5> in <module>----> 1 not_defined
NameError: name 'not_defined' is not defined
UnboundLocalError

作为 SyntaxError 的子类,当局部变量被引用前没有赋值时报错。

def fun():    a = a + 1fun()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
input-26-ffaf665429bf> in <module>2     a = a + 13 ----> 4 fun()input-26-ffaf665429bf> in fun()1 def fun():----> 2 a = a + 13 4 fun()
UnboundLocalError: local variable 'a' referenced before assignment
LookupError IndexError

作为 LookupError 的子类,当列表的索引超出范围时报错(对元组也适用)。

l = [1, 2, 3]l[1031]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
input-27-e0d31b3ef28e> in <module>1 l = [1, 2, 3]----> 2 l[1031]
IndexError: list index out of range
KeyError

作为 LookupError 的子类,当字典的键没有定义时报错。

d = {'code':'JD', 'price':42}d['CEO']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
input-28-54414ce3d92d> in <module>1 d = {'code':'JD', 'price':42}----> 2 d['CEO']
KeyError: 'CEO'
ArithmeticError ZeroDivisionError

作为 ArithmeticError 的子类,当做除法分母为零时报错。

1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
input-33-9e1622b385b6> in <module>----> 1 1/0
ZeroDivisionError: division by zero
OverflowError

作为 ArithmeticError 的子类,当运算结果太大而不能被表示时报错。

import mathmath.exp(1031)
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
input-47-daa1e6fe64b9> in <module>1 import math----> 2 math.exp(1031)
OverflowError: math range error
FloatingPointError

作为 ArithmeticError 的子类,以 numpy 里的操作为例,只有当把 seterr 中的参数 invalid 设置 'raise' 时,当给负数开根号时报错。

import numpynumpy.seterr(invalid='raise')numpy.sqrt(-1)
---------------------------------------------------------------------------
FloatingPointError Traceback (most recent call last)
input-59-3619e85afd49> in <module>1 import numpy2 numpy.seterr(invalid='raise')----> 3 numpy.sqrt(-1)
FloatingPointError: invalid value encountered in sqrt
TypeError

当某种操作不兼容两种不同类型的变量时报错(比如整数加字符串)。

1031 + '1031'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
input-61-95f206b79753> in <module>----> 1 1031 + '1031'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
ValueError

当对函数传入无效的参数时报错。

int('@')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
input-62-29f13fe27c63> in <module>----> 1 int('@')
ValueError: invalid literal for int() with base 10: '@'
AttributeError

当对象没有某种属性而被调用时报错(比如整型对象没有 append 方法,这是列表对象里的方法)。

a = 1a.append(2)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
input-65-1a0b9c61ae63> in <module>1 a = 1----> 2 a.append(2)
AttributeError: 'int' object has no attribute 'append'
OSError

操作系统错误的类别。

FileNotFoundError

作为 OSError 的子类,当要打开的文件不存在时报错。

f = open('No Such File.txt')
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
input-67-48a6865b4125> in <module>----> 1 f = open('No Such File.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'No Such File.txt'
ImportError

当导入模块下的函数失败时报错,比如 numpy 中 没有 sqr 方法,只有 sqrt 方法。

from numpy import sqr
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
input-72-1c9f27eff610> in <module>----> 1 from numpy import sqr
ImportError: cannot import name 'sqr' from 'numpy' (C:\Users\oawsy\AppData\Local\Continuum\anaconda3\lib\site-packages\numpy\__init__.py)
ModuleNotFoundError

当导入模块不存在时报错,比如将 numpy 误打成 numqy。

import numqy
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
input-68-c1372635685c> in <module>----> 1 import numqy
ModuleNotFoundError: No module named 'numqy'
StopIteration

当在迭代器中使用 next() 函数超出其所含元素个数的范围时报错。

i = iter([1,2,3])i
0x25af5c859e8>
print(next(i))print(next(i))print(next(i))print(next(i))
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
 in
      2 print(next(i))
      3 print(next(i))
----> 4 print(next(i))

StopIteration:
3具体实例

以用 OOP 来编写 Black-Scholes 解析解为例。首先引用 numpy 和 scipy 包下的函数。

from numpy import log, sqrt, expfrom scipy import stats

编写以下 BSM 类来计算期权价格。

8b4bd229f02df85cfc13531196dc290a.png

创建一个看涨期权对象。

opt = BSM('Call', 100, 105, 0.05, 0, 1, 0.2)type(opt)
__main__.BSM

计算其期权价值,没有报错。

opt.value()
8.021352235143176

但是如果不小心的话,可能会犯以下错误。

比如忘记打反括号 - SyntaxError

opt.value(
File "", line 1
    opt.value(
              ^
SyntaxError: unexpected EOF while parsing

比如把 value() 记成了 price() - AttributeError

opt.price()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
input-22-08da04670da7> in <module>----> 1 opt.price()
AttributeError: 'BSM' object has no attribute 'price'

比如把 opt 打成了 opt1 - NameError

opt1.value()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
input-23-63b689f52380> in <module>----> 1 opt1.value()
NameError: name 'opt1' is not defined

比如将 S0 的数值 100 输成了 '100' - TypeError

opt1 = BSM('Call', '100', 105, 0.05, 0, 1, 0.2)opt1.value()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
24-46a0ecb04b28> in <module>1 opt1 = BSM('Call', '100', 105, 0.05, 0, 1, 0.2)
----> 2 opt1.value()18-9e07cba9d523> in value(self)18 19     def value(self):
---> 20         return self.omega * (self.S0*exp(-self.q*self.T)*stats.norm.cdf(self.omega*self.d1()) \21                              - self.K*exp(-self.r*self.T)*stats.norm.cdf(self.omega*self.d2()))TypeError: can't multiply sequence by non-int of type 'numpy.float64'

虽然以上的错误看起来有些弱智,但是用户在输入时指不定出什么幺蛾子,各种情况都要考虑进来保证程序不会崩。

4总结

三大错误类型:语法错误(容易识别),运行错误(较易识别)和逻辑错误(不易识别)。

常见错误类型:

  • SyntaxError(语法报错)

  • IndexError(序列中没有该索引)

  • KeyError(字典中没有该键)

  • ValueError(传入无效参数)

  • NameError(未声明/初始化对象 )

  • TypeError(对不同类型操作无效)

  • AttributeError(调用对象中不存在的属性)

本帖将用 Python 编程的错误做了个系统的梳理,then so what?有错就要改不是吗?这就是下帖的内容,异常处理(exception handling)。

f02f71f629ebf44f4514316e5c93d344.png

本书参加当当每满100减50的活动

优惠码:STCBMN

简说Python

3e31df670b555fdfe72c2857e818af3b.png

长按扫码关注,一起学Python

学习更多:整理了我开始分享学习笔记到现在超过250篇优质文章,涵盖数据分析、爬虫、机器学习等方面,别再说不知道该从哪开始,实战哪里找了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值