Python基础语法(一)迭代器、生成器、异常处理
迭代器
可迭代对象
在Python中凡是可以通过“for i in 序列”遍历的都是可迭代对象,也可以通过isinstance(序列,Iterable)查看。
创建可迭代对象:
只要对象中含有_ _ ter _ _()方法,它就是一个可迭代对象:
示例:
from collections import Iterable
list1=[1,2,3,4]
tuple1=(1,2,3,4)
set1={1,2,3,4}
dict1={1:'a',2:'b',3:'c',4:'d'}
class test():#自定义可迭代对象类
def __iter__(self):
pass
t=test()
print("\nlist1是不是可迭代对象:",isinstance(list1,Iterable))#True
for l1 in list1:
print(l1,end=" ")#1 2 3 4
print("\ntuple1是不是可迭代对象:",isinstance(tuple1,Iterable))#True
for t1 in tuple1:
print(t1,end=" ")#1 2 3 4
print("\nset1是不是可迭代对象:",isinstance(set1,Iterable))#True
for s1 in set1:
print(s1,end=" ")#1 2 3 4
print("\ndict1是不是可迭代对象:",isinstance(dict1,Iterable))#True
for d1 in dict1:
print(d1,end=" ")#1 2 3 4
print("\nt是不是可迭代对象:",isinstance(t,Iterable))
迭代器对象
可迭代对象不等于迭代器,迭代器是一个可以记录遍历位置的对象,它不会像序列遍历一样,一下子将全部数据生成,而是根据需要来生成数据,这样会做可以大大节省内存资源,我们可以通过isinstance(对象,iterator)判断是否为迭代器。
创建迭代器对象:
包含有_ _iter _ _ ()和 _ _ next _ _()方法的对象是迭代器对象,_ _ _iter _ _ ()返回一个特殊的迭代器对象,这个对象自动调用 _ _ next _ _()方法返回一个值,最后抛出异常Stopiteration结束迭代。
示例:
from collections import Iterator, Iterable
class test():
def __iter__(self):
pass
def __next__(self):
pass
t=test()
print("\nt是不是可迭代对象:",isinstance(t,Iterable))#True
print("\nt是不是迭代器对象:",isinstance(t,Iterator))#True
完整的迭代器:
一个完整的迭代器不仅仅要包含方法,还要能实现功能;_ _ iter _ _ ()需要返回一个迭代器对象,而 _ _ next _ _()则需要记录数值,并返回数值。
示例:
from collections import Iterator, Iterable
class test():
def __init__(self,n):
self.start=1
self.end=1
self.nlen=n
def __iter__(self):
return self#返回迭代器对象,自己是迭代器,所以可以返回自己
def __next__(self):
if self.end<=self.nlen:#迭代未完就进入返回值操作
n1=self.start#记录数值
self.start+=1#改变数值
self.end+=1#改变个数
return n1#抛出数值
else:#迭代完成就抛出异常
raise StopIteration
t=test(10)
print("t是不是可迭代对象:",isinstance(t,Iterable))#True
print("t是不是迭代器对象:",isinstance(t,Iterator))#True
print("单独获取:",next(t))#1
print("遍历获取:",end="")
for i in t :#因为1被取出了,所以从2开始取
print(i,end=" ")#2 3 4 5 6 7 8 9
注意:
1、可迭代对象不一定是迭代器对象
2、迭代器对象一定是可迭代对象
3、list、tuple、set、str、dict是可迭代对象,但不是迭代器对象。
生成器
生成器和迭代器相类似,他们都不会一下子生成全部数据,而是根据需要生成,生成器里面存放的是生成数值的算法,它不会立即执行,而是你什么时候调用,就什么时候执行并返回数值,当你需要大量数据又不想占用太多内存时,就可以使用生成器。
创建生成器
1、()推导式创建:
g1=(i for i in range(10))#()推导式可创建一个生成器对象
print(next(g1))#获取第一个值:0
print(next(g1))#获取第二个值:1
print(next(g1))#获取第三个值:2
print(type(g1))#获取对象类型:<class 'generator'>
2、yield关键字创建:
def test(l):
num=0
while num<=l:#使用yield关键字最好配合上循环
num+=1
yield num#暂停函数,抛出num,下次调用next从这里的下一句执行,
#如果后面没有yield会报错,所以要配合循环
t=test(10)
print(type(t))#<class 'generator'>
print(next(t))#获取第一个值:1
print(next(t))#获取第一个值:2
print(next(t))#获取第一个值:3
3、yield关键字创建+传参:
import time
def test(l):
num=0
while num<=l:
num+=1
res=yield num
print(res)
t=test(10)
print(type(t))#<class 'generator'>
print(t.send(None))#传递空值,开启生成器,抛出1,暂停函数
time.sleep(1)
print(t.send(10))#执行yield后面语句,打印res:10,抛出2,暂停函数
time.sleep(1)
print(t.send(20))#执行yield后面语句,打印res:20,抛出3,暂停函数
异常处理
异常是指在语法逻辑正确的情况下出现的问题,例如我们在做计算器时,除数不能为0,而用户又输入的0,这时候系统就会抛出异常,我们需要对异常进行捕捉和处理,异常除了可以由系统抛出外,还可以是人为抛出。
系统抛出异常
try-except语句(常见用法)
try后面的代码块放置的是可能出现异常的代码块,当出现异常后会被捕捉,执行except后面的异常处理代码块,没有异常的话不执行异常处理,except可以写多个。
语法格式:
try:
可能引发异常的代码块
except [,异常类型 as e]:
捕捉到异常后的处理代码块
示例:
try:
num=int(input())
print(10/num)
except ZeroDivisionError as e:#异常分类处理,输入0的情况
print("0不可以作为除数!")
except ValueError as e:#输入非数字的情况
print("你输入的不是数字!")
注意:
异常只能被捕捉一次,当有多个except时,把异常类按范围从小到大排,因为当前面的大异常类把异常捕捉了,后面的后面就捕捉不到,这样不利于对异常情况的分类
try-except-else语句
try-except-else语句在前者的基础上加了else这个分支,else的作用和except相反,当没有异常时执行else后面的代码块,else分支可写可不写,没有强制要求。
语法格式:
try:
可能产生异常的代码块
except 异常类 as e:
捕获到异常后的处理代码块
else:
没有异常时的代码块
示例:
try:
num=int(input())
print(10/num)
except ZeroDivisionError as e:
print("0不可以作为除数!")
except ValueError as e:
print("你输入的不是数字!")
else:#当没有异常时,输出结果后,输出“顺利计算完成”;有异常时不输出“顺利计算完成”
print("顺利计算完成")
try-except-else-finally 语句
该语句是在上句的基础上引入了finally分支,这个finally的作用是无论有没有异常都会执行finally后面的代码块,finally也是可写可不写,非强制要求。
语法格式:
try:
可能产生异常的代码块
except 异常类 as e:
捕获到异常后的处理代码块
else:
没有异常时的代码块
finally:
有没有异常都要执行的代码块
示例:
try:
num=int(input())
print(10/num)
except ZeroDivisionError as e:
print("0不可以作为除数!")
except ValueError as e:
print("你输入的不是数字!")
else:
print("顺利计算完成")
finally:#不管是否出现异常都会输出“本次计算过程全部完成”
print("本次计算过程全部完成")
人为抛出异常
断言(assert)
断言用于判断,当某些条件不成立(False)时,抛出AssertionError。
语法格式:
assert 表达式,错误信息
示例:
try:
num=int(input())
assert num>0,"输入的必须是正数!"#设置断言,当num>0不成立时,抛出AssertionError异常
print(10/num)
except ZeroDivisionError as e:
print("0不可以作为除数!")
except ValueError as e:
print("你输入的不是数字!")
except AssertionError as e:#捕捉断言抛出的异常
print(e)#打印错误信息
else:
print("顺利计算完成")
finally:
print("计算过程全部完成")
手动抛出异常(raise)
如果需要人为抛出异常就需要用到raise关键字,它和assert相类似,不过raise可以指定抛出异常的类型,raise经常配合自定义经常类使用。
创建自定义异常类:
class myerror(Exception):#异常类必须继承自Exception
def __init__(self,*args,**kwargs):
if args:
self.error=args
if kwargs:
self.error=kwargs
def __str__(self):
return str(*self.error)
语法格式:
raise 异常类(错误信息)
示例:
class myerror(Exception):
def __init__(self,*args,**kwargs):
if args:
self.error=args
if kwargs:
self.error=kwargs
def __str__(self):
return str(*self.error)
try:
num=int(input())
assert num>0,"输入的必须是正数!"
if num>99:#当num大于99时,触发自定义异常类,抛出异常
raise myerror("数值范围过大!")#抛出的异常可以是自定义异常类也可以是系统异常类
if num%10!=0:
raise#只有raise时默认抛出RuntimeError
print(10/num)
except myerror as e:#捕获异常
print(e)#打印错误信息
except ZeroDivisionError as e:
print("0不可以作为除数!")
except ValueError as e:
print("你输入的不是数字!")
except AssertionError as e:
print(e)
else:
print("顺利计算完成")
finally:
print("计算过程全部完成")