当前位置:   article > 正文

python except用法和作用_3800 字 Python 流程控制专题总结

python except用法和作用

c6f802b05adfadff7cd4932c78cf5f0f.png

我的完整施工计划

已完成专题:

1.我的施工计划

2.数字专题

3.字符串专题

4.列表专题

今天流程控制专题 流程控制与代码的执行顺序息息相关,流程控制相关的关键字,如if,elif,for,while,break,continue,else,return,yield,pass等。

本专题详细总结与流程控制相关的基础和进阶用法,大纲如下:

  • 基础用法

    • 1 if 用法

    • 2 for 用法

    • 3 while,break,continue

  • 进阶用法

    • 4 for 使用注意

    • 5 range 序列

    • 6 Python特色:循环与else

    • 7 pass 与接口

    • 8 return 和 yield

    • 9 短路原则

  • 总结

基础用法

专题的开始,先总结与流程控制相关的基础用法。

1 if 用法

if 对应逻辑控制的条件语句,它的基本结构可以表示为:如果满足某个条件,则怎么怎么样。

如下函数maxChunksToSort中,如果满足当前数组nums的索引i等于区间[0,i]的最大值,则[0,i]区间能被分割为一个Chunk.

def maxChunksToSort(nums):    maxn, count = nums[0], 0    for num in nums:        maxn = max(maxn, num)        if i == maxn:            count += 1    return count

if后的语句指定了一个条件,若满足if则,:后的语句成立。

如果if不满足,再使用elif判断其他情况,可以一直写elif,若是最后一个判断条件,可使用else,其基本结构为:

if A:    print('condition A meets')elif B:    print('condition B meets')elif C:    print('condition C meets')else:    print('other conditions meets')

2 for 用法

Python的for除了具备控制循环次数外,还能直接迭代容器中的元素。

控制循环次数:

for i in range(1, len(nums)):    print(i)

还能直接操作容器内的元素:

= [1, [24], [57]]for item in a:    print(item)

3 while,break,continue

while后面紧跟一个判断条件,若满足条件则会一直循环,直到不满足条件时退出。但这不是绝对的,如果while后的语句块内含有break,即便条件依然满足,但遇到break也会一样退出。

如下检测输入是否为整数,直到输入整数时,执行break退出while循环:

while True:    a = input('please input an Integer: ')    try:        ai = int(a)        print('输入了一个整数 %d ,input 结束' % (ai,))        break    except:        print("%s isn't a Integer" % (a,))

做如下测试:

please input an Integer1.21.2 isn't a Integerplease input an Integer: 1输入了一个整数 1 ,input 结束

continue与最近的循环语句forwhile组合,表示接下来循环体内的语句不执行,重新进入下一次遍历。

def f(nums):    for num in nums:        if num <= 0:            continue        print('得到一个大于0的数 %d' % (num,))

做如下测试:

得到一个大于0的数 2得到一个大于0的数 4

进阶用法

基础用法保证我们能够应付日常遇到的基本的代码流程,不过要想进一步深入理解Python特色的、与顺序相关的执行功能,还需要理解下面的进阶用法。

4 for 使用注意

for 语句遍历容器类型或可迭代类型时,如果涉及到增加、删除元素,就需要小心。比如请先看下面的例子:

删除列表中的某个元素值,可能有重复,要求元素顺序不变,空间复杂度为O(1),如果像下面这样写就会有问题:

def delItems(nums, target):    for item in nums:        if item == target:            nums.remove(item)    return nums

对于大多数情况,上面的代码无法暴露出bug。但是考虑下面输入(特点:被删除的值连续出现):

= delItems([213113], 1)print(r)

打印结果为:[2,3,1,3]

对于刚接触编程的朋友对此很不解,为什么其中一个1未被remove.

不管是Python, Java, C++,列表或数组删除元素时,其后面的元素都会逐次前移1位,但是for依然会正常迭代,因此“成功”规避了相邻的后面元素1.

图形解释命中目标后的一系列动作:

2d4451b1efb972597edb68526894d1a1.png
上面的列表
2ac400e3e42523961f8a228669862b4d.png
命中目标
de7ccc0f40abc3b8f3be8f51fe55f28e.png
删除元素1

下步最关键:解释器自动前移删除位置后的所有元素

bded920ac882d10bd952f535f3d8705f.png

但是,等到下一次迭代时,迭代器不等待,正常移动到下一个位置:

a412f4e27ef1206fe8274ffa9e292c4a.png

这样元素3成功逃避是否与目标值相等的检查。

结论:命中目标处的后一个位置都逃避了是否与目标值相等的检查,所以一旦有连续目标值,必然就会漏掉,进而触发上面的bug.

明白上面这个原因后,重新再改写一遍删除所有重复元素的代码,下面代码不再使用for直接遍历元素(再说一遍:增删元素原来迭代器发生改变,所以会导致异常行为),而是使用索引访问:

def delItems(nums, target):    i = 0    while i         if nums[i] == target:            del nums[i]            i -= 1        i += 1    return numsr = delItems([213113], 1)print(r) # [2,3,3]

如果元素等于target,从数组nums中删除nums[i],删除后解释器自动将i后的元素都前移1位。据此,巧妙的控制i值,一旦命中立即i减去1,这样确保不漏检查。

5 range 序列

range在Python中经常用于生成一串数字序列,对刚入门Python的朋友想尝试打印其中的值:

In [3]print(range(10))range(010)

要想看到每个值可与for结合:

In [21]: for i in range(10):    ...:     print(i,end=",")    ...:0,1,2,3,4,5,6,7,8,9,

那么有的朋友不禁要问range函数的返回值为什么能与for结合?

类型为Iterable的对象都可与for结合,下面确认range(10)返回值是否为Iterable:

In [13]: from collections.abc import IterableIn [14]: isinstance(range(10),Iterable)Out[14]: True # 它是 Iterable 类型

它为什么不是一次全部输出一个列表,就像下面这样:

In [23]: list(range(10))Out[23]: [0123456789]

而是要一个一个的输出?

range函数为了高效节省内存,一次只返回一个值,而不是直接将构成序列的全部元素加载到内存。

Python里的range不支持创建浮点序列,所以为了更加清楚的展示range的原理,编写一个创建浮点数的序列frange

def frange(startstop, step):    i = start    while i         yield i        i += step

代码只有几行,yield作为控制流程的一个关键字,下面我们会详细说到。

使用frange

fr = frange(01.,0.2)for i in fr:    print("{:.2f}".format(i),end=",")

打印结果如下,得到一个差值为0.2的等差数列:

0.00,0.20,0.40,0.60,0.80,

6 Python特色:循环与else

6.1 for能和else组对

Python一大特色:while,for能和else组对,不仅如此,try exceptelse也能组对,下面介绍它们存在的价值。

找出2到15的所有素数,如果不是素数打印出一对因子,实现代码如下:

for num in range(216):    is_prime = True     for item in range(2, num):        if num % item == 0:            print('%d = %d*%d ' % (num, item, num // item))            is_prime = False            break    if is_prime:        print("%d is prime" % (num))

打印结果如下:

2 is prime3 is prime4 = 2*25 is prime6 = 2*37 is prime8 = 2*49 = 3*310 = 2*511 is prime12 = 2*613 is prime14 = 2*715 = 3*5

使用is_prime标志位判断是否找到num的一对因子,若都遍历完仍无发现则打印此数是素数。

这是我们比较熟悉的常规解决思路,但是如果使用forelse组对,它的价值便能体现出来:

for num in range(216):    for item in range(2, num):        if num % item == 0:            print('%d = %d*%d ' % (num, item, num // item))            break    else:        print("%d is prime" % (num))

上面代码实现同样的功能,但代码相对更加简洁。通过前后代码对比,我们便能看出forelse组对的功能:for遍历完成后执行else,但是触发break后,else不执行。

大家平时多多使用,便能习惯以上用法。通过上面的对比,我们也能直观的感受到它们的价值。

6.2 try,exceptelse 组对

try 和 except 组对比较容易理解,触发异常执行 except 里的代码,否则不执行。

但是加上一个else实现怎样的作用呢?

首先看下面的例子:

In [9]: while True:   ...:     try:   ...:         a = int(input('请输入一个整数: '))   ...:     except ValueError:   ...:         print('input value is not a valid number')   ...:     else:   ...:         if a % 2 == 0:   ...:              print('输入的 %d 是偶数' %(a,))   ...:         else:   ...:             print('输入的 %d 是奇数' %(a,))   ...:         break

测试:

请输入一个整数: tinput value is not a valid number请输入一个整数: 5输入的 5 是奇数

try 保护的代码正常通过后,else才执行。

有的朋友会问,为什么不把else这块代码放到try里面?这还是有一定区别的:放到else中意味着这块代码不必受保护,因为它不可能触发ValueError这样的异常。

7 pass 与接口

Python中最特别的关键字之一便是pass,它放在类或函数里,表示类和函数暂不定义。

class PassClass:    passdef PassFun():    pass 

如上实现最精简的类和函数定义。

今天跟大家分享一个pass的特别有用的用法,尤其对Java语言的interfaceimplements等较熟悉的朋友,在Python中也能实现类似写法。

首先安装一个包:

pip install python-interface

下面是这个包的基本用法,首先创建一个接口类:

from interface import implements, Interfaceclass MyInterface(Interface):    def method1(self, x):        pass    def method2(self, x, y):        pass

下面实现接口:

class MyClass(implements(MyInterface)):    def method1(self, x):        return x * 2    def method2(self, x, y):        return x + y

这个包对熟悉Java语言的朋友还是非常实用,接口和实现类用法,可以平稳过渡到Python语言中。

8 return 和 yield

程序遇到 returnyield 都是立即中断返回。那么yieldreturn又有什么不同呢?

return不同,yield中断返回后,下一次迭代会进入到yield后面的下一行代码,而不像return下一次执行还是从函数体的第一句开始执行。

用图解释一下:

6b1741aac16f8c28b8a1d7b0e53496c7.png
遇到yield中断返回

第一次 yield 返回 1

fa2545209c263b560670115c4b1f1863.png

第二次迭代,直接到位置2这句代码。

然后再走for ,再yield,重复下去,直到for结束。

以上就是理解yield的重要一个点,当然yield还会与from 连用,还能与send实现协程等,这些都放在后面的专题。

9 短路原则

最后以一个有意思的短路问题结束流程控制专题。

布尔运算符 andor 也被称为短路运算符:它们的参数从左至右解析,一旦可以确定结果解析就会停止。

Python中的短路运算符常见的有两个:and , or

A and B : 如果 A 不成立,B 不会执行

A or B : 如过 A 成立,B不会执行

所以被称为短路运算符

举几个例子一看就明白,请看下面代码:

代码1:

= ''= a and 'i will not execute'print(b)

打印结果为空,因为and运算符从左到右检查,一旦a为空即为假,则结果已确定为假,'i will not execute'被短路。

代码2:

a = 'python'b = a or 'i will not execute'print(b)

打印结果为:python,因为or运算符从左到右检查,一旦a为真则结果已确定为真,所以'i will not execute'被短路。

总结

本专题细致总结了流程控制的基础和进阶用法,具体包括以下:

  • 基础用法

    • 1 if 用法

    • 2 for 用法

    • 3 while,break,continue

  • 进阶用法

    • 4 for 使用注意

    • 5 range 序列

    • 6 Python特色:循环与else

    • 7 pass 与接口

    • 8 return 和 yield

    • 9 短路原则

  • 总结

《end》

送书环节:非常感谢华章出版社对这篇原创文章的赞助,特意赠送我们《机器学习实战》4本,此书每本售价82.7元:

af739db9edfdf1a6d978791ee701b72c.png

振哥也比较这本书,所以自己留1本,剩余的3本送给大家。送书方法:我会综合考虑以下指标:留言被点赞数,留言走心程度(必须),过去一周公众号活跃度(主要指标:文章赞赏、分享、留言情况),综合这些送书3本,截止时间7月10日晚10:00,到时我会在文章下以回复留言的方式通知你中奖。

这本书真心不错,可点击下方查看详情:

最后,原创不易,真心希望朋友们三连支持,这样我会更有动力完成下一个专题的编写。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/778562
推荐阅读
相关标签
  

闽ICP备14008679号