python二刷


python课件总结

[toc]

ps:

这份笔记并不完整,是笔者学了一遍粗糙的python后二刷看课件觉得有用的东西,课件想要的私聊,不贵不贵,一杯奶茶:laughing:

还有那份课件的题目值得一做!

1.语言基础

面向对象 、 解释型 、 动态数据类型

变量与地址

Python 解释器会为每个出现的对象分配内存单元,即使它们的值相等,也会这样

为了 提高内存利用效率,对于一些简单的对象,如一些数值 较小(-256~256 )的 整型(int )对象,Python 采取重用对象内存的办法

单独的下画线(_ )是一个特殊变量,用于表示上一次运算的结果

Math

整数二进制0b\0B开头,八进制0o\0O开头,十六进制0x\0X开头

对于浮点数,Python 3.x 默认提供17 位有效数字的精度,相当
于C 语言中的双精度浮点数

可以通过x.real 和x.imag 来分别获取复数x 的实部和虚部,结果都是浮点型,是j不是i

数学常量:e pi

函数:

fabs sqrt pow(x,y) exp log(x[,base])(base默认是e) log10()

ceil floor

fmod(x,y) # x/y的余数 (浮点)

degrees <=> radians

sin cos tan asin acos atan(默认用弧度)

Cmath模块函数基本一致,但是对复数运算

cmath.sqrt(-1) ij 用的是j不是i

cmath 模块包括复数 运算特有的 函数。

复数x=a+bi ,phase(x) 函数返回复数x 的幅 角,即atan(b/a) 。

Random

seed设置种子,默认将系统时间设为种子值

choice(seq) :从 序列的元素中随机挑选一个 元素 。

sample(seq,k) :从 序列中随机挑选k 个元素。

shuffle(seq) :将 序列的所有元素随机排序 ,这个只能用于可更改的,字符串不可用

时间和日历

datetime基于time进行了优化,更方便全面

datetime

from datetime import datetime,date,time
dt = datetime(2021,5,1,21,8,30)
dt.year,month,day,hour,minute,second
dt.date()输出前三个
dt.time()输出后三个

dt.strftime('%x%x%x')
datetime.strptime('202151',"%Y%m%d")#转换为datetime对象!!这个是datetime下的datetime子类!!!
datetime相减会产生datetime.delta对象
delta = datetime2 - datetime1
delta == datetime.timedelta(99,7179) #间隔99天,7179秒
timedelta和datetime可以做加减得到新的datetime
%y     两位数的年份表示(00-99*%Y     四位数的年份表示(000-9999*%m     月份(01-12*%d     月内中的一天(0-31*%H     24小时制小时数(0-23*%I     12小时制小时数(01-12*%M     分钟数(00=59*%S     秒(00-59*%a     本地简化星期名称
*%A     本地完整星期名称
%b     本地简化的月份名称
%B     本地完整的月份名称
%c     本地相应的日期表示和时间表示
%j     年内的一天(001-366%p     本地A.M.或P.M.的等价符
%U     一年中的星期数(00-53)星期天为星期的开始
%w     星期(0-6),星期天为星期的开始
%W     一年中的星期数(00-53)星期一为星期的开始
%x     本地相应的日期表示
%X     本地相应的时间表示
%Z     当前时区的名称
%%     %号本身

详述

python内置

range iter

帮助

Python 中能表示浮点数的有效数字是有限的,而在实际应用中数据的有效位数并无限制,这种矛盾,势必带来计算时的微小误差。

2.顺序结构

在Python 中,语句行从解释器提示符后的第一列开始, 前面不能有任何空格 ,否则会产生语法错误

Python 中的赋值并不是直接将一个值赋给一个变量的,而是通过引用传递的,在赋值时,不管这个对象是新创建的还是一个已经存在的,都是将该对象的 引用( 并不是值 )

同步赋值指的是多变量一条式子赋值时,实际上先创建了一个元组,先后顺序不影响

eval()去掉字符串最外侧的引号

print(xxx[,sep =][,end = ])

字符串format方法

这才是王道

用序号调整次序,重复什么的很方便

注意这个居中填充,还有居中不对称时左边少一个

print('what {1:<10}{0}the {c:&<10.1f}'.format('a','b',c = 21.311))
what b         athe 21.3&&&&&&
In [3]: print('what {1:<10}{0}the {c:&=+10.1f}'.format('a','b',c = 21.311))
what b         athe +&&&&&21.3

3.循环结构

for 语句是通过遍历任意序列的元素进行来建立循环的,针对序列的每一个元素执行一次循环体

首先Python 对关键字in 后的对象调用iter() 函数获得迭代 器,然后 调用next() 函数获得迭代器的 元素,直到 抛出stopIteration

while 语句多用于循环次数不确定的情况,而对于循环次数确定的情况,使用for

pass空语句

注意 :布尔常量True 和False 首字母必须大写 !

4.字符串

建议看看原文

编码

万国码Unicode是python选择的标准符号表,它每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求(翻译二进制码的方式)

ASCII 码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节。

UTF-8 编码中,一个英文字为一个字节,一个中文为三个字节。

Unicode 编码中,一个英文为一个字节,一个中文为两个字节。

字节只是一个单位(8位)罢了,不同的编码中采用不同的规则存储字符,而这些规则实现的时候消耗字节大小不同

UTF-8

​ 是 一种为Unicode 字符设计的变长编码系统

对于ASCII 字符,UTF-8 仅使用1 个字节来编码

Unicode规定了,所有字符统一由两个字符来表示,也就是16位

utf-8就是缩小一点,从4到8到12到16分段

详述有一点错误就是最后那个中文例子,看我的👇

而python字符串默认是unicode编码

In [1]: a = '卧槽'

In [2]: a[0]
Out[2]: '卧'

In [3]: a.encode('utf-8')
Out[3]: b'\xe5\x8d\xa7\xe6\xa7\xbd' #一个汉字拆成三个字节
    
In [10]: c = 'dnoad'
In [11]: c.encode('utf-8')
Out[11]: b'dnoad'
# 英文在utf-8中不会发生转换,直接用一个字节表示
In [13]: ord('我')
Out[13]: 25105 #unicode
    
In [14]: chr(25104)
Out[14]: '成'

分片的操作很灵活,开始和结束 的索引值 可以超
过字符串的长度

字符串用 + 和 *

但是在解释器里面,都是输出普通的’abc’

Python 的字符串是不可变类型,只能通过新建一
个字符串去改变一个字符串的元素

字符比较是按其计算机内部字符编码值的大小进
行比较,西文字符按ASCII 码值大小进行比较

比较的基本规则是,空格字符最小,数字比字母
小,大写字母比小写字母小( 对应字母相 差32

函数。。

prefix和suffix是字符串,start 可以选择开头位置,end我不知道干嘛的

split如果两个分隔符中没东西,也会拆出空字符串,从左右拆顺序不变,可能只影响matsplit参数

那个splitlines试了一下:

c = 'dada\nwdad'
c
Out[51]: 'dada\nwdad'
print(c)
dada
wdad
c.splitlines()
Out[53]: ['dada', 'wdad']

字节类型

和字符串一样,可以使用内置的len() 函数求bytes对象的长度,也可以 使用“+ ” 运算符连接两个bytes 对象,其操作结果是一个新的bytes 对象

如果需要改变某个字节,可以组合使用字符串的分片和连接操作(效果跟字符串是一样的), 也可以 将bytes 对象转换为bytearray 对象,bytearray对象是可以被修改的

可以 使用编号给bytearray 对象的某个字节赋值 , 并且这个值必须是0~255 之间的一个整数

也 不允许针对bytes 对象的出现次数进行计数,因为字符串里面 根本没有字节字符

encode和decode可以在两者间转换

5.正则

看我的博客了解基础知识

在Python 中,正则表达式的功能通过正则表达式
模块re

re 模块提供各种正则表达式 的匹配 操作,在文本解析、复杂字符串分析和信息提取时是一个非常有用的工具。

使用

正则表达式中,group()用来提出分组截获的字符串,()用来分组

import  re
a  =  "123abc456"
print  re.search( "([0-9]*)([a-z]*)([0-9]*)" ,a).group( 0 )    #123abc456,返回整体
print  re.search( "([0-9]*)([a-z]*)([0-9]*)" ,a).group( 1 )    #123
print  re.search( "([0-9]*)([a-z]*)([0-9]*)" ,a).group( 2 )    #abc
print  re.search( "([0-9]*)([a-z]*)([0-9]*)" ,a).group( 3 )    #456
  1. 正则表达式中的三组括号把匹配结果分成三组
  • group() 同group(0)就是匹配正则表达式整体结果
  • group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
  1. 没有匹配成功的,re.search()返回None

注意到匹配模式串使用了原始字符串r’ ‘

match() 方法并不是完全匹配。当正则表达式结束时,若string 还有剩余字符 ,仍然视为 成功

想 要完全匹配,可以在表达式末尾加上边界匹配符’$


match() 函数只是在字符串 的左端位置 尝试匹配正则表达式,也就是只报告从位置0 开始的 匹配情况。

如果想要搜索整个字符串来寻找匹配,应当用search() 函数 ,使用方法完全一样

findall() 函数搜索字符串,以列表形式返回全部能匹配正则表达式的子串 。

finditer() 与findall() 函数类似,在字符串中找到正则表达式所匹配的所有子串,并组成一个迭代器返回。


subn() 函数的功能和sub() 函数 相同,但 返回新的字符串以及替换的次数组成的元组 。


两个斜杠噢,第一次先让编译器把两个斜杠转成一个斜杠,第二步到正则字符串则把剩下的单斜杠看成是转义

6.列表&元组

len() min() max()

sum()返回序列s中所有元素和,元素必须为数值

reduce 位于functools模块中

reduce(f,s[,n]) :reduce() 函数把序列s 的前两个元素作为 参数,传 给函数f ,返回 计算的结果和 序列的下一个元素重新作为f 的参数,直到序列的最后一个元素

enumerate 和 zip不必多言

利用* 号操作符,可以将对象解压 还原

>>> t
[('a', '1'), ('b', '2'), ('c', '3')]
>>> m=zip(*t)
>>> list(m)
[('a', 'b', 'c'), ('1', '2', '3')]

还有sorted reversed all any

加星号的变量只允许一个,否则会出现语法错误syntaxError 。

列表可以进行元素赋值(索引不能超)

元素删除 del 分片赋值 在使用分片赋值时,可使用与原序列不等长的序列将分片替换

for前面的部分是一个表达式,它必须根据x计算出一个结果,必须加上else,如:

[x if x % 2 == 0 else -x for x in range(1, 11)]

列表常用方法

  1. 序列都可以用

并不改变序列本身,可用于列表,元组,字符串

s.count(x) :返回x 在序列s 中出现的次数

s.index(x) :返回x 在s 中第一次出现的下标

不过x是完整的

  1. 仅使用列表

s.reverse() :将列表s 中的元素逆序排

s.pop([i]) :删除并返回列表s 中指定位置i 的元素,默认是最后一个元素。若i 超出列表长度 ,则 抛出IndexError 异常

s.insert(i,x) :在列表s 的i 位置处插入x 。如果i 大于列表的长度,则插入到列表最后 。

可以看看题目

7.字典

更新和创建都用索引,删除则用del,检查关键字用in / not in

len() 函数可以获取字典所包含“关键字: 值”对的数目,即字典长度 。虽然 也支持max() 、min() 、sum() 和sorted() 函数,但只针对字典的关键字进行计算,很多情况下没有实际意义。

字典不支持连接(+) 和重复操作符(*) ,关系运算中只有“==” 和“!=” 有意义

常用方法

dict三用法:

  1. 使用dict() 函数创建一个空字典并给变量赋值

  2. 第二种方法应该是大规模处理中用的多的

Python 字典和集合实际上也是对象,Python 提供了很多有用的方法。

原先的键会被清除,字符串也可以做序列, 重复的键会被删除

d2 = d.fromkeys(('dwad'))
d2
Out[92]: {'d': None, 'w': None, 'a': None}

8.集合

在Python 中, 集合( set )是 一个无序排列的、不重复的数据集合体,类似于数学中的集合概念 ,可 对其 进行并、 交、 差等 运算

集合和字典都属于无序集合体,有许多操作是一致的

在Python 中,用大括号将集合元素括起来,这与字典的创建类似,但{} 表示空字典,空集合用set()表示。

集合 的 自动删除重复元素 这个特性非常有用,例如,要删除列表中大量的重复元素,可以先用set()函数将列表转换成集合,再用list() 函数将集合转换成列表,操作效率非常高。

Python 提供frozenset() 函数来创建不可变集合,不可变集合是不能修改的,因此能作为其他集合的元素,也能作为字典的关键字。

传统运算

比较用 == 和 != 还有包含真包含 < <=

当然还有赋值运算符 s1 |= s2

集合与for 循环语句配合使用,可实现对集合各个元素的遍历

常用方法

  1. 适用于可变和不可变集合

s.copy() :复制集合s 。

  1. 适合可变集合的方法

9.函数与模块

在Python 中,实参向形参传送数据的方式是“值传递”,即“拷贝”或“复制”

实参 的值传给形参 ,是对象间整体赋值,是 一种单向传递方式,不能由形参传回给实参。

主函数

参数传递

1. 必选参数就是位置参数,必须填,
2. 默认参数可填可不填。默认参数有个坑,就是每次调用函数,默认参数的指向不便且会保存,所以可修改,每次都不一样,因此定义默认参数要牢记一点:默认参数必须指向不变对象!
3. 然后就到可变参数,指的是可以接受所有值的元组,*args  放在第三位接受所有的
4. 第四是命名关键字,或者说可变字典**kw  接受所有的 a = 'xxx' 这样的参数,并赋给字典,但是key不用加引号
5. 最后是关键字参数,不能省略的键值对!
#其实就是无限接受的放在后面。

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, city, job):
    print(name, age, city, job)
    
和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符**后面的参数被视为命名关键字参数。
调用方式如下:
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def person(name, age, *args, city, job):
    print(name, age, args, city, job)
    
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given
#命名关键字参数可以有缺省值,从而简化调用

函数参数规则:

  1. 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
  2. 对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。
  3. 虽然可以组合多达5种参数,但不要同时使用太多的组合,否则函数接口的可理解性很差。

注意 **dict解包作为参数时,是复制一份,也就是传值


当在 函数内部修改列表、字典的 元素时,形参的改变会影响实参,即双向传递,类似于“传地址”、“共享内存”、“借”,

匿名函数lambda

lambda [ 参数1[, 参数2,……, 参数n]]: 表达式

关键字lambda 表示匿名函数,冒号前面是函数参数,可以有多个函数参数,但只有一个返回值 ,所以只能有一个表达式,返回值就是该表达式的结果。

image-20211105121650828

装饰器

这个讲的比一般的清楚一点所以放在这。

装饰器 (decorator ,[ˈdekəreɪtə(r)] )可简单地理解为一个函数,这是一个用来包装函数的函数,经常用于为已经存在的函数添加额外的功能

当多个函数有重复代码时,可以将此部分代码单独拿出来整理成一个 装饰 器,然后对每个函数调用该装饰器,这样可以实现代码的复用,而且可以让原来的函数更轻便 。

当 需要为多个己经写好的函数添加一个共同功能,例如检查参数的合法性时,就可以单独写一个检查合法性的装饰器,然后在每个需要检查参数合法性的函数处调用即可,而不用去每个函数内部修改

无参数

把@deco 语句放在函数square_sum() 定义之前,实际上是将square_sum 传递给装饰器deco ,并将deco 返回的新函数对象赋给原来的函数名 square_sum=deco(square_sum)

从本质上,装饰器起到的就是这样一个重新指向函数名的作用,让同一个对象名指向一个新返回的函数,从而达到修改可调用函数的目的

最外层定义deco的本体,把函数传进去,里面定义新函数,新函数肯定要调用到原来的函数。如果需要传参数,就在本体外面再加一层传递参数的壳。

有参数

要注意多重装饰器的执行顺序,应该是先执行后面的装饰器,再执行前面的装饰器。

global

在程序中定义全局变量的主要目的是,为函数间的数据联系提供一个直接传递的通道 。

因此不要滥用全局变量

模板有条件执行

模块 中可以是一段 可以 直接执行的 程序(也称为
脚本 ) , 也可以定义一些变量、类或函数,让别的模块导入和调用, 类似于库。

模块中的定义部分,例如全局变量定义、类定义、函数定义等,因为没有程序执行入口,所以 不能直接运行,但对主程序代码部分有时希望只让它在模块直接执行的时候才执行,被其他模块加载时就不执行。

在Python 中,可以通过系统变量“__name__”(注意前后都是两个下画线)的值来区分这两种情况。 如果模块是被其他模块导入的,__name__ 的值是模块的名称,主动执行时它的值就是字符串“__main__” 。

通过__name__ 变量的这个特性,可以将一个模块文件既作为普通的模块库供其他模块使用,又可以作为一个可执行文件进行 执行。

10.面向对象

面向对象程序设计(Object-Oriented programming ,OOP )则以对象作为程序的主体,将程序和数据封装于其中,以提高软件的重用性、灵活性和扩展性

面向对象程序设计是按照人们认识客观世界的系统思维方式,采用基于对象的概念建立问题模型,模拟客观世界,分析、设计和实现软件的办法

面向对象语言的三大核心内容是封装(类和对象)、 继承(派生)和 多态

class A:

x = 5

我定义了一个类A,这个时候自动出现了个类对象A,我可以使用A.x调用类属性

“ .” 运算符:成员运算符

类中的实例方法至少应有 一 个变量 参数,一般命名为“ self ”( 习惯,非语法要求) ) ,而且该参数必须 作为形参表的第一 个参数,即必须放 于形式参数 表的最左边

实例的方法和对象只能实例调用,不能类调用,这不是废话嘛

属性

类 属性(class attribute )是类的 属性,它被 所有类对象和实例对象共有 ,在内存中只存在一个副本

公有 的类属性,在类外可以通过类对象和实例对象访问 ,但是不提倡用实例对象访问,容易绕晕

类属性还可以在类定义结束之后通过类 名(类对象)增加 比如 A.new = 212

实例对象也 可以在类定义结束之后通过实例对象名增加实例属性

方法

只要创建实例对象,就一定要调用构造方法

只要调用了构造方法,就一定创建了实例对象

构造方法重载:

  1. 使用默认参数
  2. 构造方法根据条件调用其他的自定方法
  3. 构造方法根据条件执行不同的操作,可以用*arg来接受数量未知的参数

具体方法

实例方法必须有一个参数放在最左端,self

一点详解

@staticmethod 静态方法只是名义上归属类管理,但是不能使用类变量和实例变量,是类的工具包
放在函数前(该函数不传入self或者cls),所以不能访问类属性和实例属性

静态方法没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。

继承和多态

从已有类产生新类的过程就称为类的派生(derivation)(派生是继承的另一种说法)

多重 继承(multiple inheritance )是指一个子类有两个或多个直接父类,子类从两个或多个直接父类中继承所需的 属性和方法。

class 子类名( 父类名1, 父 类名2,…):

Python 本身是一种 解释型语言 ,不进行编译,因此它就只在运行时 确定 其状态,故也可以说Python 是一种多态语言 。

高级操作

__slot__,限制示例对象能自主添加的属性。

image-20211105155310776

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查(在setter里),这样,程序运行时就减少了出错的可能性。

https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208

class Screen(object):
    @property #相当于getter
    def width(self):
        return self.__width

    @width.setter
    def width(self, value):
        self.__width = value

    @property
    def height(self):
        return self.__height

    @height.setter
    def height(self, value):
        self.__height = value

    @property
    def resolution(self):
        return 786432

dir 返回所有的方法和属性,包括私有的和隐藏的,私有的会变成 _类名__属性

hasattr getattr setattr

还可以将object提供的类的诸多参数比如__len__ \ __call__override来自定义类

11.文件操作

这个把我的心态搞炸了一会

首先python里的默认编码都是Unicode,所有的文件其实本质都是二进制码,二进制文件只能用bytes类型操作,读出来怎么解读自己来,一般都用Unicode规则来decode( 二进制文件 是把数据按其在内存中的存储形式原样输出到磁盘上存放。)

小心那个文件指针位置,你写入了以后会放在最后,再读取啥都读不出来类似的

Python你在读写文件的时候不要打开。。不然会出现更改不了。。

理解python的opentxt默认是ANSI编码,不是UTF-8,坑死了,解决方案👈

经常需要用到“终端形式”阅读的,用文本,经常修改的,最好用二进制

读/ 写操作是相对于磁盘文件而言的,而输入/ 输出操作是相对于内存储器而言的

r+是从最开始开始读的

文件对象=open( 文件说明符[, 打开方式][, 缓冲区])


文件对象有一些属性

文本

文本文件是指以ASCII 码方式存储的文件:英文、数字等字符存储的是ASCII 码 ,而 汉字存储的是机内码。

文本文件中除了存储文件有效字符信息(包括能用ASCII 码字符表示的回车、换行等信息)外,不能存储其他任何信息

文本文件的 优点:方便 阅读和理解,使用常用的文本编辑器或文字处理器就可以对其创建和修改的,文件 对象提供了read() 、readline() 和readlines() 方法 用于读取文本文件的内容

每次write() 方法 执行完后并不 换行,如果 需要换行则在字符串最后加 换行符“\n

读取中文问题:

InIn [6]: f = open('try.txt','r+')

In [7]: a = f.read()
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-7-648df9718e18> in <module>()
----> 1 a = f.read()

UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 8: illegal multibyte sequence
    默认gbk

In [8]: f = open('try.txt','r+',encoding = 'utf-8')

In [9]: a = f.read()

In [10]: a
Out[10]: '我是中文'
    
In [11]: f.write('现在能输中文吗')
Out[11]: 7 #成功了

二进制

seek()偏移为正数表示朝文件尾方向移动,偏移为负数表示朝文件头方向移动;

文本文件 存放的是与编码对应的字符,而二进制文件直接存储字节编码。

struct模块

读文件的时候,可以一次读出4 个字节,然后用unpack() 方法转换成Python 的整数 。

注意:unpack() 方法执行后得到的结果是一个元组。

如果写入的数据是由多个数据构成的,则需要在pack() 方法中使用格式串

此时的bytes 就是二进制形式的数据了,可以直接写入二进制文件 。当需要时可以读出来,再通过struct.unpack() 方法解码成Python 变量

pickle模块

在pickle 模块中有2 个常用的方法:dump() 和load()

pickle.dump( 数据,文件对象)

其功能是直接把数据对象转换为字节 字符串,并保存到文件中 。

OS

Python 的os 模块提供了类似于操作系统级的文件管理功能,如文件重命名、文件删除、目录管理等

os.rename(“ 当前文件名”,” 新文件名”)

os.remove(“ 文件名”)

os.mkdir(“ 新目录名”)

os.chdir(“要成为当前目录的目录名”)

getcwd() 方法显示当前的工作目录。

os.rmdir(“ 待删除目录名”) 在用rmdir() 方法删除一个目录前,先要删除目录中的所有内容。

12.异常

程序中的错误通常分为 语法错误 、 运行错误 和 逻辑错误 。

语法 错误是由于程序中使用了不符合 语法规则 的信息而导致的 ,这类错误比较 容易 修改,因为编译器或解释器会指出错误的位置和性质

运行错误则不容易修改,因为其中的错误是 不可预料的,或者可以预料但无法避免 的, 例如:内存 空间不够、数组下标越界、文件打开失败等

逻辑错误 主要表现在程序运行后,得到的结果与设想的结果不一致,通常出现逻辑错误的程序都能正常运行系统 不会给出提示信息,所有很难发现。

良好的程序应该对用户的不当操作做出提示,能识别多种情况下的程序运行状况,并选择适当 的应对 策略

在程序中,对各种可预见的异常情况进行处理称为异常处理(exception handling)

处理程序异常的方法有很多,最简单和最直接的办法是在发现异常时,由Python 系统进行 默认的异常处理

如果 异常对象未被处理或者捕捉,程序就会用所谓的 回溯(Traceback ) 终止

标准错误信息包括两个部分:错误类型(如NameError )和错误说明(如name ‘A’ is not defined ),两者用冒号分隔

Python 系统还追溯错误发生的位置,并显示有关
信息

捕获

异常处理

try:
    xxx
except 异常类型1[as 错误描述]:
    xxx
except 异常类型2[as 错误描述]:
    xx......
except:
    默认异常处理语句块
else:
    语句块

当发生异常时,直接跳转到except,try中没执行完的语句会被跳过嗷!

可以嵌套。

finally 子句是指无论是否发生异常都将执行相应的
语句块 。

断言

在编写程序时,在程序调试阶段往往需要判断程序执行过程中变量的值,根据变量的值来分析程序的执行情况

可以 使用print() 函数打印输出结果,也可以通过断点跟踪调试查看变量,但使用断言更加灵活高效 。

a,b = eval(input())
assert b!=0,'除数不可为0'
c = a/b
print(c)

Lenovo@LAPTOP-08D3H5DC MINGW64 ~/Desktop/env
$ D:/Anaconda3/envs/TF2/python.exe c:/Users/Lenovo/Desktop/env/one.py
2,0
Traceback (most recent call last):
  File "c:/Users/Lenovo/Desktop/env/one.py", line 2, in <module>
    assert b!=0,'除数不可为0'
AssertionError: 除数不可为0

AssertionError 异常可以被捕获,并像使用在try-except 语句中的任何其他异常处理,但如果不处理,它们将终止程序并产生回溯

主动引发异常与自定义类

前面的异常类都是由Python 库中提供的,产生的异常也都是由Python 解释器引发的

在程序设计 过程中,有时需要在编写的程序中主动引发异常,还可能需要定义表示特定程序错误的异常类。

在Python 中,要想自行引发异常,最简单的形式就是输入关键字raise ,后跟要引发的异常的名称

异常 名称标识出具体的类,Python 异常处理是这些类的对象 。 raise 语句还可指定对异常对象进行初始化的参数 ,执行raise 语句时,Python 会创建指定的异常类的一个对象

处理学生成绩时,成绩不能为负数。利用前面创建的NumberError 异常类,处理出现负数成绩的异常 。


文章作者: Darren
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Darren !
评论
  目录