小甲鱼python入门笔记(三)

目录

十三、函数

4、作用域

(1)局部作用域

(2)全局作用域

(3)global语句

(4)嵌套函数

(5)nonlocal语句

(6)LEGB规则

5、闭包

6、装饰器

7、lambda表达式

8、生成器

实现生成器的两种方法

(1)使用yield语句替换函数中的return

(2)生成器表达式

9、递归

汉诺塔

10、函数文档、类型注释、内省

(1)函数文档

(2)类型注释

(3)内省

11、高阶函数

functools模块

十四、永久储存

1、打开文件

(1)创建并打开文件,open()函数

(2)文件对象的各种方法

2、路径处理

(1)路径查询相关操作

(2)修改路径相关操作

3、上下文管理器:with语句

4、pickle模块

十五、异常

1、程序报异常

2、捕获并处理异常

(1)try-except

(2)try-except-else

(3)try-except-finally

(4)完整try语句语法

3、异常嵌套

4、raise语句,主动抛出异常

5、assert语句

6、利用异常来实现goto


十三、函数

4、作用域

变量可以别访问的范围。

(1)局部作用域

变量的定义为在函数中,那么其作用域就在该函数中,称为局部变量

(2)全局作用域

在函数外部定义一个变量,那么其作用域就在全局,称为全局变量

在函数中,同样名称的局部变量会覆盖全局变量

(3)global语句

在函数内部定义一个全局变量

>>> x = 123
>>> def fun():
	global x
	x = 456
	print(x)
	
>>> fun()
456
>>> print(x)
456

(4)嵌套函数

内层函数无法在全局调用

>>> def funa():
	x = 111
	def funb():
		x = 222
		print('在内层的X是', x)
	funb()
	print('在外层的x是', x)

>>> funa()
在内层的X是 222
在外层的x是 111

>>> funb()
Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    funb()
NameError: name 'funb' is not defined

(5)nonlocal语句

在内部函数修改外部函数的变量

>>> def funa():
	x = 111
	def funb():
		nonlocal x
		x = 222
		print('在内层的X是', x)
	funb()
	print('在外层的x是', x)

>>> funa()
在内层的X是 222
在外层的x是 222

(6)LEGB规则

当各个作用域覆盖范围重复,出现冲突的时候,按此规格执行。L最高,B最低。
L:Local,局部作用域
E:Enclosed,嵌套函数的外层函数作用域
G:Global,全局作用域
B:Build-In,内置作用域(内置函数,内置方法)

若使用内置函数名创建全局变量,将不能再使用内置函数的功能。因此避免命名与内置函数同名的变量或者函数等。

>>> int = 123
>>> int('123')
Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    int('123')
TypeError: 'int' object is not callable

5、闭包

1、利用嵌套函数的外层作用域具有记忆能力这个特性让数据保存在外层函数的参数或者变量中
2、将内层函数作为返回值,就可以从外部间接的调用到内层的函数。

开篇例:在嵌套函数外部作用域中的一些变量是可以通过一些方法保存下来的。

>>> def funa():
	x = 123
	def funb():
		print(x)
	funb()
	
>>> funa()
123
>>> def funa():
	x = 123
	def funb():
		print(x)
	return funb

>>> funa()
<function funa.<locals>.funb at 0x000001E978DB5040>
>>> funa()()
123
>>> fun = funa()
>>> fun()
123

闭包:工厂函数

>>> def power(exp):
	def exp_of(base):
		return exp ** base
	return exp_of

>>> square = power(2)
>>> cube = power(3)
>>> square(2)
4
>>> square(3)
8
>>> cube(2)
9
>>> cube(3)
27
>>> def outer():
	x = y = 0
	def inner(a, b):
		nonlocal x, y
		x += a
		y += b
		print(x, y)
	return inner

>>> move = outer()
>>> move(1, 2)
1 2
>>> move(3, 4)
4 6

6、装饰器

将函数作为参数传递给另一个函数

>>> def myfunc():
	print('这里是myfunc')
	
>>> def report(func):
	print('这里是report')
	func()
	print('这里是report')
	
>>> report(myfunc)
这里是report
这里是myfunc
这里是report

(1)将闭包和将函数作为参数综合起来就是装饰器。

import time
def time_master(func):
    def call_func():
        print('开始运行程序...')
        start = time.time()
        func()
        end = time.time()
        print(f'运行结束,用时{(end - start):5f}')
    return call_func

def myfunc():
    print('myfunc是为了打印这个字符串')

myfunc = time_master(myfunc)

myfunc()

>>> 
==== RESTART: C:\Users\chaos\AppData\Local\Programs\Python\Python39\text.py ====
开始运行程序...
myfunc是为了打印这个字符串
运行结束,用时0.004998

通过参数将函数传入time_master,func就执行myfunc的语句,而后将call_func作为函数的返回值返回,赋值给myfunc,调用myfunc就相当于把两个函数的内容都执行了一遍。

(2)装饰器语法糖:@time_master

import time
def time_master(func):
    def call_func():
        print('开始运行程序...')
        start = time.time()
        func()
        end = time.time()
        print(f'运行结束,用时{(end - start):5f}')
    return call_func

@time_master
def myfunc():
    print('myfunc是为了打印这个字符串')

myfunc()

>>> 
==== RESTART: C:\Users\chaos\AppData\Local\Programs\Python\Python39\text.py ====
开始运行程序...
myfunc是为了打印这个字符串
运行结束,用时0.005981

(3)多个装饰器可以用在同一个函数上。若有多个装饰器,则从下往上执行,先执行@trp,再@mul,再@sum

def sum(fun):
    def inner():
        x = fun()
        return x + 1
    return inner
def mul(fun):
    def inner():
        x = fun()
        return x*x
    return inner
def trp(fun):
    def inner():
        x = fun()
        return x*x*x
    return inner

@sum
@mul
@trp
def myfunc():
    return 2
print(myfunc())

>>> 
==== RESTART: C:\Users\chaos\AppData\Local\Programs\Python\Python39\text.py ====
65

(4)给装饰器传递参数

import time
def log(msg):
    def time_master(func):
        def call_func():
            start = time.time()
            func()
            end = time.time()
            print(f'{msg}程序用了{(end - start):.5f}')
        return call_func
    return time_master

@log('A')
def funcA():
    print('打印了funcA中的字符串')
@log('B')
def funcB():
    print('打印了funcB中的字符串')

funcA()
funcB()

>>> 
==== RESTART: C:\Users\chaos\AppData\Local\Programs\Python\Python39\text.py ====
打印了funcA中的字符串
A程序用了0.04354
打印了funcB中的字符串
B程序用了0.00630

@log('A') 相当于 funcA = log('A')(funcA)
@log('B') 相当于 funcB = log('B')(funcB),先调用log()并向其传参'B',随后调用time_master,并将函数funcB传入

7、lambda表达式

匿名函数

lambda arg1, arg2, arg3, ...argN : expression

相当于:def <lambda>(arg1, arg2, arg3, ...argN):
                        return expression

因为lambda是一个表达式,所以它可以做一些常规函数不能做到的事
例如将lambda表达式作为元素放到列表中;将lambda用到map、filter函数中;

>>> func = lambda x:x*x
>>> func(2)
4

>>> y = [lambda x:x*x, 2, 3]
>>> y[0](y[2])
9

>>> mapped = map(lambda x:ord(x), 'Love')
>>> list(mapped)
[76, 111, 118, 101]

>>> filted = filter(lambda x:x % 2, range(10))
>>> list(filted)
[1, 3, 5, 7, 9]

8、生成器

实现生成器的两种方法

(1)使用yield语句替换函数中的return

让函数在退出之后还能保留状态,除了使用闭包以及全局变量以外,还可以在函数中使用yield语句来代替return,也就是生成器。

生成器会在每调用一次的时候提供一个数据,并且记住当时的状态,支持next()函数,无法使用下标索引

>>> def counter():
	i = 0
	while i <= 3:
		yield i
		i += 1
		
>>> counter()
<generator object counter at 0x000001922FA6C740>
>>> for i in counter():
	print(i, end = ' ')
	
0 1 2 3
>>> c = counter()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
>>> next(c)
3
>>> next(c)
Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    next(c)
StopIteration
>>> c = counter()
>>> c[2]
Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    c[2]
TypeError: 'generator' object is not subscriptable

使用生成器实现斐波拉契数列

>>> def F():
	x, y = 0, 1
	while y <= 100:
		yield y
		x, y = y, x + y
		
>>> for i in F():
	print(i, end = ' ')
	
1 1 2 3 5 8 13 21 34 55 89 

(2)生成器表达式

>>> (i ** 2 for i in range(3))
<generator object <genexpr> at 0x000001922FB4DB30>
>>> i = (i ** 2 for i in range(3))
>>> next(i)
0
>>> next(i)
1
>>> next(i)
4
>>> next(i)
Traceback (most recent call last):
  File "<pyshell#85>", line 1, in <module>
    next(i)
StopIteration

9、递归

递归就是函数调用自身的过程

要让递归进行正常工作,必须设置一个结束条件,并且在运行过程中需要向这个条件推进。

>>> def funA(i):
	if i > 0:
		print('Love')
		i -= 1
		funA(i)
		
>>> funA(5)
Love
Love
Love
Love
Love

使用递归方法是实现阶乘

>>> def fact(i):
	if i == 1:
		return 1
	else:
		return i * fact(i-1)
	
>>> fact(5)
120

汉诺塔

>>> def hanoi(n, x, y, z):
    if n == 1:
        print(x, '-->', z)
    else:
        hanoi(n-1, x, z, y)
        print(x, '-->', z)
        hanoi(n-1, y, x, z)
        
>>> n = int(input('请输入汉诺塔的层数:'))
请输入汉诺塔的层数:3
>>> hanoi(n, 'A', 'B', 'C')
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C

10、函数文档、类型注释、内省

(1)函数文档

在定义函数的时候,在语句前用字符串形式插入。使用help()调用。内置函数也有。

>>> def exchange(dollar, rate = 6.32):
	"""
	功能:美元汇率转换
	参数:
	- dollar:美元数量
	- rate:美元汇率,默认值为6.32
	返回值:
	- 人民币数量
	"""
	return dollar * rate

>>> exchange(10)
63.2
>>> help(exchange)
Help on function exchange in module __main__:

exchange(dollar, rate=6.32)
    功能:美元汇率转换
    参数:
    - dollar:美元数量
    - rate:美元汇率,默认值为6.32
    返回值:
    - 人民币数量

>>> help(print)
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

(2)类型注释

s:str表示还函数的作者希望调用该函数的人员传入s参数的实参是str类型,可使用默认参数
n:int表示还函数的作者希望调用该函数的人员传入n参数的实参是int类型,可使用默认参数
-> str表示该函数的返回值是str类型

虽然有类型注释,但是如果在调用函数的时候往里面传入的参数并不符合注释的类型,python是不会报错的。若想让python对调用传入的参数进行检测,检测其是否符合类型注释,可以使用第三方模块Mypy

>>> def sstr(s:str, n:int) -> str:
	return s * n

>>> sstr('Love', 2)
'LoveLove'

>>> def sstr(s:str = 'hot', n:int = 5) -> str:
	return s * n

>>> sstr()
'hothothothothot'

(3)内省

指在程序运行的时候可以进行自我检测的一种机制。python通过一些特殊的属性来实现内省的。

>>> sstr.__name__#输出函数的名字
'sstr'
>>> sstr.__annotations__#输出函数的类型注释
{'s': <class 'str'>, 'n': <class 'int'>, 'return': <class 'str'>}
>>> exchange.__doc__#输出函数的文档
'\n\t功能:美元汇率转换\n\t参数:\n\t- dollar:美元数量\n\t- rate:美元汇率,默认值为6.32\n\t返回值:\n\t- 人民币数量\n\t'
>>> print(exchange.__doc__)

	功能:美元汇率转换
	参数:
	- dollar:美元数量
	- rate:美元汇率,默认值为6.32
	返回值:
	- 人民币数量

11、高阶函数

当一个函数接收另一个函数作为参数的时候,就称这个函数为高阶函数。

functools模块

python中包含实用高阶函数以及装饰器的模块

reduce()函数:
functools.reduce(function, iterable[ ,initializer])
将iterable 可迭代对象中的元素作为参数依次应用到function函数中,最终返回累计的结果。

>>> def add(x, y):
	return x+y

>>> import functools
>>> functools.reduce(add, [1, 2, 3, 4, 5])#相当于↓
15
>>> add(add(add(add(1, 2), 3), 4), 5)
15
>>> functools.reduce(lambda x,y:x*y, range(1, 11))
3628800

partial()函数,偏函数
functools.partial(func, /,  *args,**keywords)
对指定的函数进行二次包装,通常是将现有的函数部分参数预先绑定,得到的新函数即为偏函数。
也就是将一个函数的多个参数进行拆分,分为多次传递。

>>> square = functools.partial(pow, exp = 3)
>>> square(2)
8
>>> ssum = functools.partial(sum, start = 3)
>>> ssum([1, 2, 3])
9

@wraps装饰器

装饰器的副作用:在使用了装饰器之后,装饰器装饰过的函数已经不是其本身了,是装饰器内部的函数,则导致函数名与其实际引用的函数名不一致。

>>> def zhuangshi(func):
	def inner():
		print('调用了inner')
	return inner
>>> @zhuangshi
def outer():
	print('调用了outer')

>>> outer.__name__  #副作用在这里
'inner'

@wraps装饰器主要用来装饰装饰器

>>> import functools        #导入了functools模块
>>> def zhuangshi(func):
	@functools.wraps(func)  #使用装饰器装饰了装饰器
	def inner():
		print('调用了inner')
	return inner

>>> @zhuangshi
def outer():
	print('调用了outer')
	
>>> outer.__name__   #没有副作用啦
'outer'

十四、永久储存

1、打开文件

(1)创建并打开文件,open()函数

open()函数用于打开一个文件并返回其对应的文件对象。
open(file, mode= 'r ' , buffering=-1, encoding=None,errors=None,newline=None,closefd=True,opener=None)

参数 含义
file指定一个将要打开的文件的路径(绝对路径或相对路径)
mode可选参数,指定文件的打开模式:
字符串含义
'r'读取(默认)
'w'写入(如果文件已存在则先截断清空文件)
'x'排他性创建文件(如果文件已存在则打开失败)
'a'追加(如果文件已存在则在末尾追加内容),注1
'b'二进制模式,注2
't'文本模式(默认),注3
'+'更新文件(读取和写入)

更多参数请查看函数文档。

>>> f = open('D:/mypy/text.txt', 'w')
>>> f
<_io.TextIOWrapper name='D:/mypy/text.txt' mode='w' encoding='cp936'>

随后在D:/mypy文件夹创建一个新文件text.txt,若未指定文件夹路径,则直接在python安装目录中创建文件,随后在该文件夹中可以看见新创建的文件。成功创建之后会返回文件对象,将文件对象赋值给变量f。

(2)文件对象的各种方法

方法含义
f.close()关闭文件对象
f.flush()将文件对象中的缓存数据写入到文件中(不一定有效)
f.read(size=-1,/)从文件对象中读取指定数量的字符(或者遇到EOF停止)﹔当未指定该参数,或该参数为负值的时候,读取剩余的所有字符
f.readable()判断该文件对象是否支持读取(如果返回的值为False,则调用read()方法会导致OSError异常)
f.readline(size=-1,/)从文件对象中读取一行字符串(包括换行符),如果指定了size参数,则表示读取 size个字符
f.seek(offset,whence=0,/)修改文件指针的位置,从whence参数指定的位置((0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移 offset个字节,返回值是新的索引位置
f.seekable()判断该文件对象是否支持修改文件指针的位置(如果返回的值为False,则调用seek(),tell(),truncate()方法都会导致OSError异常)
f.tell()返回当前文件指针在文件对象中的位置
f.truncate(pos=None, /)将文件对象截取到pos 的位置,默认是截取到文件指针当前指定的位置
f.write(text, /)将字符串写入到文件对象中,并返回写入的字符数量(字符串的长度)
f.writable()判断该文件对象是否支持写入(如果返回的值为 False,则调用write()方法会导致OSError异常)
f.writelines(lines, /)将一系列字符串写入到文件对象中(不会自动添加换行符,所以通常是人为地加在每个字符串的末尾)

将字符串写入到文件中,使用write()writeline()方法。
执行写入代码之后马上打开文件,并不能立即看见写入的内容,因为写入的内容还在文件的对象的缓冲区,只有将文件对象关闭之后,数据才能写入文件中。

使用flush()方法可以在不关闭文件的情况下将缓存区的内容写入文件。

>>> f.write('歪卜八卜')
4
>>> f.writelines(['玛卡巴卡\n', '唔西迪西'])
>>> f.close()

更新文件内容用'r+','r+'模式既可以读取也可以写入
文件对象是可迭代的,可以使用循环读取
可以通过read()readline()方法读取文件,read读取到文件末尾,readline读取一行。

文件对象内部有文件指针,负责指向文件的当前位置,当在文件中读取一个字符的时候,文件指针就会指向下一个字符,直到文件末尾EOF(end of the file),因为之前使用了for语句对文件进行了读取,所以现在的文件指针指向了文件的末尾,所以使用f.read()没有返回字符。

使用tell()方法追踪文件指针的位置。

使用seek()方法修改文件指针。

>>> f = open('d:/mypy/text.txt', 'r+')
>>> f.writable()
True
>>> f.readable()
True

>>> for i in f:
	print(i)
	
歪卜八卜玛卡巴卡

唔西迪西

>>> f.read()
''
>>> f.tell()
26
>>> f.seek(0)
0
>>> f.readline()
'歪卜八卜玛卡巴卡\n'
>>> f.read()
'唔西迪西'

2、路径处理

pathlib --面向对象的文件系统路径
pathlib是Python3.4之后新添加的模块,它可以让文件和路径操作变得快捷方便,完美代替os.path模块。

(1)路径查询相关操作

cwd():获取当前目录路径
is_dir():判断一个路径是否为一个文件夹
is_file():判断一个路径是否为一个文件
exists():检测一个路径是否存在
name:获取路径的最后一个部分
stem:获取文件名
suffix:获取文件后缀
parent:获取父级目录
parents:获取逻辑祖先路径构成的不可变序列,支持索引
parts:将路径的各个组件拆分成元组
stat():查询文件或文件夹的信息
resolve():将相对路径转换为绝对路径
iterdir():获取当前路径下所有子文件和子文件夹

>>> from pathlib import Path

>>> Path.cwd()
WindowsPath('C:/Users/chaos/AppData/Local/Programs/Python/Python39')
>>> p = Path('C:/Users/chaos/AppData/Local/Programs/Python/Python39')
>>> p
WindowsPath('C:/Users/chaos/AppData/Local/Programs/Python/Python39')
>>> q = p / 'text.txt'
>>> q
WindowsPath('C:/Users/chaos/AppData/Local/Programs/Python/Python39/text.txt')

>>> p.is_dir()
True
>>> q.is_dir()
False

>>> p.is_file()
False
>>> q.is_file()
True

>>> q.exists()
True

>>> p.name
'Python39'

>>> q.stem
'text'

>>> q.suffix
'.txt'

>>> p.parent
WindowsPath('C:/Users/chaos/AppData/Local/Programs/Python')

>>> ps = p.parents
>>> for i in ps:
	print(i)
	
C:\Users\chaos\AppData\Local\Programs\Python
C:\Users\chaos\AppData\Local\Programs
C:\Users\chaos\AppData\Local
C:\Users\chaos\AppData
C:\Users\chaos
C:\Users
C:\
>>> ps[3]
WindowsPath('C:/Users/chaos/AppData')

>>> p.parts
('C:\\', 'Users', 'chaos', 'AppData', 'Local', 'Programs', 'Python', 'Python39')

>>> q.stat()
os.stat_result(st_mode=33206, st_ino=15199648742442202, st_dev=1726722931, st_nlink=1, st_uid=0, st_gid=0, st_size=26, st_atime=1668584601, st_mtime=1668414575, st_ctime=1668413617)

>>> Path('./doc')
WindowsPath('doc')
>>> Path('./doc').resolve()
WindowsPath('C:/Users/chaos/AppData/Local/Programs/Python/Python39/Doc')

>>> for i in p.iterdir():
	print(i)
	
C:\Users\chaos\AppData\Local\Programs\Python\Python39\DLLs
C:\Users\chaos\AppData\Local\Programs\Python\Python39\Doc
C:\Users\chaos\AppData\Local\Programs\Python\Python39\game.py
C:\Users\chaos\AppData\Local\Programs\Python\Python39\include
.
.
.

(2)修改路径相关操作

mkdir(parents, exists_ok):创建文件夹。路径中的父文件夹不存在会报错, 将parents参数设置为parents = true,在创建文件夹的同时创建不存在的父级文件夹。若创建的文件夹已经存在会报错,若设置exists_ok = true则忽略报错信息。
open():打开文件
rename():修改文件或者文件夹的名字
replace():替换指定的文件或文件夹
rmdir():删除文件夹。若文件夹下有文件,会报错
unlink():删除文件
glob(): 功能强大的查找功能

3、上下文管理器:with语句

#正常对文件进行操作
>>> f = open('text.txt', 'w')
>>> f.write('I Love Python.')
14
>>> f.close()

#使用with语句对文件进行同样的操作
>>> with open('text.txt', 'w') as f:
	f.write('I Love Python.')
	
14

正常的对文件进行操作有时候会忘记关闭文件,或者是程序在执行到close()之前就停止了运行,这样会导致之前写入的内容丢失,使用上下文管理器则可以确保文件资源的释放。

4、pickle模块

python对象序列化,也就是说将python对象转化为二进制字节流的过程
永久储存python对象,也就是说将字符串、列表、字典等python对象保存为文件的形式,.pkl文件

dump():将对象以二进制形式写入到.pkl文件中,

import pickle
x, y, z = 1, 2, 3
with open('test.pkl', 'wb') as f:
    pickle.dump(x, f)#可以用元组进行打包
    pickle.dump(y, f)#相当于pickle.dump((x, y, z), f)
    pickle.dump(z, f)

load():从.pkl文件中读取存储的对象

import pickle
with open('test.pkl', 'rb') as f:
    x = pickle.load(f)#使用元组打包的话,读取也应该解包
    y = pickle.load(f)#相当于x, y, z = pickle.load(f)
    z = pickle.load(f)
print(x, y, z, sep = ' ')

== RESTART: C:\Users\chaos\AppData\Local\Programs\Python\Python39\readtest.py ==
1 2 3

十五、异常

1、程序报异常

查文档去

2、捕获并处理异常

(1)try-except

当检测范围内出现异常,则执行异常处理代码

>>> try:
	1/0
except:
	print('出错了')
	
出错了

若检测范围没有异常,则不会执行异常处理代码

>>> try:
	1/1
except:
	print('出错了')
	
1.0

expression用于指定想要捕获的异常,当程序异常与指定的异常相同时才会执行异常处理代码。

>>> try:
	1 / 0
except ZeroDivisionError:#指定了除数为0的异常
	print('除数为0')
	
除数为0
>>> try:
	520 + '123'
except ZeroDivisionError:#未出现除数为0的异常
	print('除数为0')
	
Traceback (most recent call last):
  File "<pyshell#15>", line 2, in <module>
    520 + '123'
TypeError: unsupported operand type(s) for +: 'int' and 'str'

也可以在该处使用元组打包多个想要捕获的异常,只要程序出现任何一个就执行异常处理代码。

>>> try:
	520 + '123'
except (ZeroDivisionError, TypeError):#元组打包多个异常
	print('出错了')
	
出错了

当想捕获多个异常,并对不用的异常分别进行处理,只需要多个except语句即可。

>>> try:
	520 + '123'#执行到该出时直接跳到对应的异常处理代码,之后的语句不执行
	1/0        
except ZeroDivisionError:
	print('除数为0')
except TypeError:
	print('数据类型出错')
	
数据类型出错

as identifier用于提取出现异常的原因

>>> try:
	520 + '123'
except TypeError as e:
	print(e)
	
unsupported operand type(s) for +: 'int' and 'str'

(2)try-except-else

当try语句执行时未出现异常,则执行else的内容

>>> try:
	520 + 123
except:
	print('类型错误')
else:
	print('没有异常')
	
643
没有异常

(3)try-except-finally

无论异常是否发生,都执行finally的内容

finally通常使用在程序收尾的地方,例如关闭文件。

>>> try:
	520 + '123'
except:
	print('类型错误')
else:
	print('没有异常')
finally:
	print('程序执行完毕')
	
类型错误
程序执行完毕
>>> try:
	520 + 123
except:
	print('类型错误')
else:
	print('没有异常')
finally:
	print('程序执行完毕')
	
643
没有异常
程序执行完毕

(4)完整try语句语法

3、异常嵌套

>>> try:
	try:
		1/0
	except:
		print('内部异常')
	520 + '123'
except:
	print('外部异常')
finally:
	print('程序结束')
	
内部异常
外部异常
程序结束

4、raise语句,主动抛出异常

>>> raise ValueError("值不正确。")
Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    raise ValueError("值不正确。")
ValueError: 值不正确。

不能用该语句生成不存在的异常

>>> raise Error("值不正确。")
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    raise Error("值不正确。")
NameError: name 'Error' is not defined

异常链

>>> raise ValueError("值不正确。") from TypeError
TypeError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    raise ValueError("值不正确。") from TypeError
ValueError: 值不正确。

5、assert语句

跟raise类似,主动引发异常,但只能引发AssertionError异常。通常用于代码调试

>>> assert 'Love' == 'love'
Traceback (most recent call last):
  File "<pyshell#53>", line 1, in <module>
    assert 'Love' == 'love'
AssertionError

6、利用异常来实现goto

>>> try:
	while True:
		while True:
			while True:
				for i in range(10):
					print(i)
					if i > 3:
						raise
			print('循环都被跳出了')
except:
	print('跳出来了')
	
0
1
2
3
4
跳出来了

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值