Python 函数对象、 名称空间与作用域、闭包、装饰器、迭代器

一、函数的对象

函数对象:函数是第一类对象,即函数可以当作数据传递

1、可以被引用

 1 def foo():
 2     print('from foo')
 3 func = foo
 4 print(foo)  #不加扩号为foo函数的内存地址
 5 print(func)   #func指向foo的内存地址
 6 func()        #加扩号执行func函数,也就是执行foo的代码
 7 
 8 """
 9 输出:
10 <function foo at 0x0000000000613E18>
11 <function foo at 0x0000000000613E18>
12 from foo
13 """

2、可以当作参数传递

 1 def foo():
 2     print('from foo')
 3 def bar(func):
 4     print(func)  #func指向foo的内存地址
 5     func()  #执行func参数,实际执行的是foo
 6 bar(foo) #foo做为bar函数的参数
 7 """
 8 输出
 9 <function foo at 0x0000000002113E18>
10 from foo
11 """

3、返回值可以是函数

 1 def foo():
 2     print('from foo')
 3 
 4 def bar(func):
 5     return func  #返回func参数也就是foo函数的内存地址
 6 
 7 f=bar(foo)  #foo函数做为bar的参数,把foo的内存地址赋值给f
 8 print(f) #打印f的内存地址
 9 f()  #执行f,也就是执行foo
10 """
11 输出:
12 <function foo at 0x0000000002473E18>
13 from foo
14 """

4、可以当作容器类型的元素

 1 def foo():
 2     print('from foo')
 3 dic={'func':foo}  #定义字典,key为func,value为foo函数的内存地址
 4 print(dic['func']) #打印dic字典中key func对应的值,也就是foo的内存地址
 5 dic['func']() #加扩号执行字典的value,也就是执行foo.
 6 """
 7 输出:
 8 <function foo at 0x0000000000773E18>
 9 from foo
10 """

5、应用

 1 def select(sql):  #定义select函数,传入sql形参
 2     print('========>select')
 3 
 4 def insert(sql):
 5     print('========>add')
 6 
 7 def delete(sql):
 8     print('=======>delete')
 9 
10 def update(sql):
11     print('-=---->update')
12 
13 
14 func_dic={          #定义func_dic字典,将函数做为字典的value值
15     'select':select,
16     'update':update,
17     'insert':insert,
18     'delete':delete
19 }
20 
21 def main():      #定义main函数
22     while True:
23         sql = input('>>: ').strip()     #输入内容赋值给sql变量
24         if not sql:continue    #判断sql不为空则继续,为空则退出
25         l = sql.split()      #sql变量切割成列表赋值给l
26         cmd=l[0]          #将l列表的索引0位置的值赋值给cmd
27         if cmd in func_dic:  #判断cmd的内容在func_dic字典中
28             func_dic[cmd](l)   #则找到cmd内容在字典中对应的value值,并扩号执行value对应的函数.
29 
30 main()  #调用main函数
31 
32 """
33 输出:
34 >>: select * from tables;
35 ========>select
36 """
37 
38 
39 def main():
40     sql = input('>>: ')
41     l = sql.split()
42     print(l)   #打印l列表,也就是sql变量切割后的内容
43     if l[0] == 'select':   #判断l列表的索引0位置的值等于 select
44         select(1)           #则执行select函数,并将l列表的索引0做为参数
45     elif l[0] == 'insert':
46         insert(l)
47     elif l[0] == 'delete':
48         delete(l)
49     elif l[0] == 'update':
50         update(l)
51 
52 main()  #调用main函数
53 """
54 输出:
55 >>: select * from tables;
56 ['select', '*', 'from', 'tables;']
57 ========>select
58 """

二、 名称空间与作用域

1、定义名字的方法

a.导入系统模块
import time
b.定义变量
name='egon'
c.自定义函数
def func():
      pass

d.定义类
 class Foo:
      pass

2、三种名称空间

1)内置名称空间:随着python解释器的启动而产生

1 print(sum)     #内置名称空间
2 print(max)
3 print(min)
4 print(max([1,2,3]))
5 
6 import builtins    #导入builtins模块,
7 for i in dir(builtins):   #查看所有内置名称空间
8     print(i)

 2)全局名称空间:在当前文件中,以及文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间

 1 x=1   #全局变量x=1
 2 def func():  #定义函数
 3     money=2000
 4     x=2      #在函数内定义x=2
 5     print(func)
 6 func()    #执行函数,可以调到全局变量
 7 print(x)    #打印x ,x仍然等于1,局部x=2 没有调到,说明应用的是当前文件,也就是全局名称空间
 8 print(money)   #money属于局部变量,调用不了
 9 """
10 输出:
11 <function func at 0x0000000002133E18>
12 1
13 """

3)局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定

x=10000
def func():
    x = 1 #局部变量
    print(x)
    def f1():
        pass
func()   #执行函数时打印函数内的局部变量x=1
"""
输出:
1
"""
print(x) #直接打印应用全局变量 x=10000
"""
输出:
10000
"""

3、作用域

1)作用域:为名称空间的具体应用。

2)作用域与名称空间的对应关系:

  全局作用域:内置名称空间,全局名层空间。

  局部作用:局部名称空间。

 1 x=1  #全局后生效
 2 def func():
 3     x=2   #局部优先生效
 4     print(x)
 5     sum=123123
 6     print(sum)
 7 func()
 8 """
 9 输出:
10 2
11 123123
12 """
13 
14 x = 1
15 def func():
16     x=2
17     
18 func()
19 print(x)
20 """
21 输出:
22 1
23 """

4)名字的查找顺序:局部名称空间---》全局名层空间---》内置名称空间

  全局作用域:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕。

  局部作用域的名字:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效。

 1 """
 2     查看全局作用域内的名字:gloabls()
 3     查看局局作用域内的名字:locals()
 4 """
 5 
 6 x=1000
 7 def func():
 8     x=2
 9     # 在局部作用域中,打印全局作用域中的名字,在该作用域中x等于1000
10     print(globals())
11     # 在局部作用域中,打印局部作用域的名字,执行结果为x等于2   {'x': 2}
12     print(locals())
13 func()
14 """
15 输出:
16 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000002579240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/S17/day04/s1.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x00000000006B3E18>}
17 {'x': 2}
18 """
19 print(globals())    #在全局作用域中,打印全局作用域中的名字,x等于1000
20 print(locals())     #在全局作用域中,打印局部作用域的名字,一层一层应用,因为当前在全局中没有局部,所以应用全局中的名字,x也等于1000
21 print(globals() is locals())   #在全局作用域中,判断全局名字是否在局部中,如果是返回True
22 """
23 输出:
24 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000002739240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/S17/day04/s1.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x0000000002483E18>}
25 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000002739240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python/S17/day04/s1.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x0000000002483E18>}
26 True
27 """

三、闭包

1、闭包,函数嵌套的一种方式,必须遵守以下规则:

  a.定义在内部函数

  b.包含对外部作用域而非全局作用域的引用,该内部函数就成为闭包函数

 1 def f1():   #定义闭包,对象隐藏,全局不可见
 2     x = 1   #x内部隐藏,全局不可见
 3     def f2():
 4         print(x)   #应用外部作用域,x=1
 5     return f2
 6 print(f1())   # return返回值为f2 ,所以f1执行结果就是f2的返回值也就是f2的内存地址
 7 a = f1()     #把f1的返回值也是就f2的内存地址 赋值给a
 8 x=2     # 全局中x=2
 9 a()         #执行a就会执行f2里的代码,应用闭包中的x=1,而非全局中的x=2
10 
11 """
12 输出:
13 <function f1.<locals>.f2 at 0x00000000025EAEA0>
14 1
15 """

2、闭包应用:惰性计算
 

 1 # 爬网页,旧方法获取网页所有代码内容
 2 from urllib.request import urlopen     #导入模块
 3 res=urlopen('http://crm.oldboyedu.com').read()
 4 print(res.decode('utf-8'))
 5 
 6 
 7 from urllib.request import urlopen
 8 def index(url):
 9     def get():
10         return urlopen(url).read()
11 
12     return get
13 #存在内存里
14 oldboy=index('http://crm.oldboyedu.com')
15 #什么时候想用,什么时候用
16 print(oldboy().decode('utf-8'))    #获取打印网页所有代码内容
17 # 闭包函数相对与普通函数会多出一个__closure__的属性,里面定义了一个元组用于存放所有的cell对象,
18 # 每个cell对象一一保存了这个闭包中所有的外部变量
19 print(oldboy.__closure__[0].cell_contents)
20 """
21 输出:
22 http://crm.oldboyedu.com
23 """
24 
25 
26 x=1
27 # y=2
28 def f1():
29     # x=1
30     y=2
31     def f2():
32         print(x,y)
33     return f2
34 
35 f=f1()
36 print(f.__closure__[0].cell_contents)
37 """
38 输出:
39 2
40 """

四、装饰器

1、装饰器:修饰别人的工具,修饰添加功能,工具指的是函数。

      装饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用对象。

2、为什么要用装饰器:

  开放封闭原则:对修改是封闭的,对扩展是开放的

  装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为其添加新功能。

 3、装饰器的基本写法

 1 """
 2     给index函数使用装饰器增加执行时间
 3 """
 4 import time
 5 
 6 def timmer(func):
 7     def wrapper():
 8         start_time=time.time()    #在执行函数前执行,获取当前时间,执行开始时间
 9         func()  #执行函数,默认没有返回值
10         stop_time=time.time()    #在执行函数后执行,获取当前时间,执行结束时间
11         print('run time is %s' %(stop_time-start_time))
12     return wrapper
13 
14 @timmer     #给index函数增加装饰器 流程分析 index=timmer(index)
15 def index():
16     time.sleep(3)
17     print('welcome to index')
18 
19 index() #执行index函数,流程分析 wrapper(index)->index()
20 """
21 输出:
22 welcome to index
23 run time is 3.0001718997955322
24 """

4、装饰器,一次定义,多次使用

 1 import time
 2 def timmer(func):
 3     def wrapper(*args,**kwargs):   # 传递参数,保证通用性,应为可变长参数(*args,**kwargs),可接受所有类型的实参
 4         start_time=time.time()
 5         res=func(*args,**kwargs)    #有返回值,存值
 6         stop_time=time.time()
 7         print('run time is %s' %(stop_time-start_time))
 8         return res     #有返回值,返回
 9     return wrapper   #返回值,返回wrapper的内存地址
10 
11 @timmer #index=timmer(index)
12 def index():
13     time.sleep(3)
14     print('welcome to index')
15     return 1   #有返回值,需要在装饰器中定义并存值
16 
17 @timmer #再次使用装饰器
18 def foo(name):
19     time.sleep(1)
20     print('from foo')
21 
22 #有返回值,传值打印
23 res=index() #wrapper()
24 print(res)
25 
26 res1=foo('merry')  #res1=wrapper('merry')
27 print(res1)
28 
29 """
30 输出:
31 welcome to index
32 run time is 3.000171661376953
33 1
34 from foo
35 run time is 1.0000569820404053
36 None
37 """

登录认证装饰器,一次定义,多次使用,因为使用了装饰器两个函数分别执行,且未保存第一次登录成功,所以需要输入两次账号密码

 1 def auth(func):
 2     def wrapper(*args,**kwargs):
 3         name=input('>>: ')
 4         password=input('>>: ')
 5         if name == 'merry' and password == '123':
 6             print('33[45mlogin successful33[0m')
 7             res=func(*args,**kwargs)
 8             return res
 9         else:
10             print('33[45mlogin err33[0m')
11     return wrapper
12 
13 
14 
15 @auth
16 def index():
17     print('welcome to index page')
18 @auth
19 def home(name):
20     print('%s welcome to home page' %name)
21 
22 index()
23 home('merry')
24 
25 """
26 输出:  #因为使用了装饰器两个函数分别执行,且未保存第一次登录成功,所以需要输入两次账号密码
27 >>: merry
28 >>: 123
29 login successful
30 welcome to index page
31 >>: merry
32 >>: 123
33 login successful
34 merry welcome to home page
35 """

登录认证装饰器,一次定义,多次使用,且一次登录成功,则无需再次登录

 1 #使用字典记录,记录用户登录状态
 2 login_user={'user':None,'status':False}
 3 def auth(func):
 4     def wrapper(*args,**kwargs):     # 传递参数,保证通用性,应为可变长参数(*args,**kwargs),可接受所有类型的实参
 5         if login_user['user'] and login_user['status']:   #判断用户状态,有值则直接返回结果
 6             res=func(*args,**kwargs)
 7             return res
 8         else:     #否则,继续用户登录
 9             name=input('>>: ')
10             password=input('>>: ')
11             if name == 'merry' and password == '123':
12                 login_user['user']='merry'
13                 login_user['status']=True
14                 print('33[45mlogin successful33[0m')
15                 res=func(*args,**kwargs)
16                 return res
17             else:
18                 print('33[45mlogin err33[0m')
19     return wrapper
20 
21 @auth
22 def index():
23     print('welcome to index page')
24 @auth
25 def home(name):
26     print('%s welcome to home page' %name)
27 index()
28 home('merry')
29 """
30 输出:   #使用字典记录用户登录状态,所以一次登录成功后,无需再次登录
31 >>: merry
32 >>: 123
33 login successful
34 welcome to index page
35 merry welcome to home page
36 """

5、有参装饰器,及多装饰器的执行顺序

 1 import time
 2 def timmer(func):
 3     def wrapper(*args,**kwargs):
 4         print('====>timmer.wrapper')
 5         start_time=time.time()
 6         res=func(*args,**kwargs) #auth_wrapper
 7         stop_time=time.time()
 8         print('run time is %s' %(stop_time-start_time))
 9         return res
10     return wrapper
11 
12 
13 
14 login_user={'user':None,'status':False}
15 def auth(driver='file'):   #定义默认形参,driver=‘file’
16     def auth2(func):
17         def wrapper(*args,**kwargs): #
18             print('=======>auth.wrapper')
19             time.sleep(5)
20             if driver == 'file':
21                 if login_user['user'] and login_user['status']:
22                     res=func(*args,**kwargs)
23                     return res
24                 else:
25                     name=input('>>: ')
26                     password=input('>>: ')
27                     if name == 'merry' and password == '123':
28                         login_user['user']='merry'
29                         login_user['status']=True
30                         print('33[45mlogin successful33[0m')
31                         res=func(*args,**kwargs)
32                         return res
33                     else:
34                         print('33[45mlogin err33[0m')
35             elif driver == 'ldap':
36                 print('==========ldap的认证')
37             elif driver == 'mysql':
38                 print('==========mysql的认证')
39                 return func(*args,**kwargs)
40             else:
41                 print('=========未知的认证来源')
42         return wrapper
43     return auth2
44 
45 
46 @auth('file') #@auth2====>index=auth2(index)===>index=auth_wrapper
47 @timmer #index=timmer(auth_wrapper) #index=timmer_wrapper
48 def index():
49     time.sleep(3)
50     print('welcome to index page')
51 @auth(driver='mysql')
52 def home(name):
53     print('%s welcome to home page' %name)
54 
55 index() #timmer_wrapper()
56 home('merry') #wrapper('merry')
57 
58 """
59 输出:
60 =======>auth.wrapper
61 >>: merry
62 >>: 123
63 login successful
64 ====>timmer.wrapper
65 welcome to index page
66 run time is 3.000171661376953
67 =======>auth.wrapper
68 ==========mysql的认证
69 merry welcome to home page
70 """

五、迭代器

1、迭代的概念:

  重复+上一次迭代的结果为下一次迭代的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值

 1 # while True: #只满足重复,因而不是迭代
 2 #     print('====>')
 3 
 4 
 5 # 下面才为迭代
 6 l = [1, 2, 3]
 7 count = 0
 8 while count < len(l):
 9     print('====>', l[count])
10     count += 1
11 
12 """
13 输出:
14 ====> 1
15 ====> 2
16 ====> 3
17 """
18 
19 l = (1, 2, 3)
20 count = 0
21 while count < len(l):
22     print('====>', l[count])
23     count += 1
24 
25 """
26 输出:
27 ====> 1
28 ====> 2
29 ====> 3
30 """
31 
32 s='hello'
33 count = 0
34 while count < len(s):
35     print('====>', s[count])
36     count += 1
37 
38 """
39 输出:
40 ====> h
41 ====> e
42 ====> l
43 ====> l
44 ====> o
45 """

2、为什么要有迭代器?

  对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式

1 # 有序的
2 [1,2].__iter__()
3 'hello'.__iter__()
4 (1,2).__iter__()
5 # 无序的
6 {'a':1,'b':2}.__iter__()
7 {1,2,3}.__iter__()

a.可迭代对象:内置了__iter__方法的,都是可迭代的对象

b.迭代器对象:执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法

c.迭代器一定是可迭代对象,但可迭代对象不一定是迭代器

 1 #列表,可迭代的对象转迭代器使用
 2 i=[1,2,3].__iter__()
 3 
 4 print(i)  #打印i的内存地址  “输出 <list_iterator object at 0x022F84F0>” 可以看到是可迭代对象
 5 
 6 print(i.__next__())
 7 print(i.__next__())
 8 print(i.__next__())
 9 print(i.__next__())   #只有三个参数,到第四次执行时没有值了,抛出异常:StopIteration
10 
11 """
12 输出:
13 <list_iterator object at 0x021484F0>
14 1
15 Traceback (most recent call last):
16 2
17   File "D:/python/s17/day04/迭代器.py", line 30, in <module>
18 3
19     print(i.__next__())   #只有三个参数,到第四次执行时没有值了,抛出异常:StopIteration
20 StopIteration
21 """
22 
23 #字典,可迭代的对象转迭代器使用
24 i={'a':1,'b':2,'c':3}.__iter__()
25 
26 print(i.__next__())
27 print(i.__next__())
28 print(i.__next__())
29 print(i.__next__())   #只有三个参数,到第四次执行时没有值了,抛出异常:StopIteration
30 
31 """
32 输出:
33 a
34 Traceback (most recent call last):
35   File "D:/python/s17/day04/迭代器.py", line 39, in <module>
36 b
37 c
38     print(i.__next__())   #只有三个参数,到第四次执行时没有值了,抛出异常:StopIteration
39 StopIteration
40 """
41 
42 #字典,可迭代的对象转迭代器使用,异常处理
43 dic={'a':1,'b':2,'c':3}    #定义字典
44 i=dic.__iter__()        #应用iter方法成为可迭代对象
45 while True:
46     try:                 #把可能有异常有代码放在try里
47         key=i.__next__()  #key等于应用了next方法的迭代器对象i
48         print(dic[key])   #打印key的值
49     except StopIteration:     #except 后加异常内容StopIteration
50         break                  #最后break打断
51 
52 """
53 输出:
54 1
55 2
56 3
57 """
58 
59 #集合,可迭代的对象转迭代器使用
60 s={'a',3,2,4}
61 s.__iter__() #iter(s)
62 
63 i=iter(s)
64 print(next(i))
65 print(next(i))
66 print(next(i))
67 print(next(i))
68 print(next(i))
69 
70 """
71 输出:
72 a
73 Traceback (most recent call last):
74 2
75   File "D:/python/s17/day04/迭代器.py", line 98, in <module>
76 3
77     print(next(i))
78 4
79 StopIteration
80 """
81 
82 # 字符串,内置函数,内部也是使用__iter__可迭代对象及__next__迭代器处理的
83 s='hello'
84 print(s.__len__())   #使用内置函数计算长度的方法__len__
85 print(len(s))       #常用代码,len(s)====== s.__len__(),两种方式都可以使用
86 """
87 输出:
88 5
89 5
90 """

4、如何判断一个对象是可迭代的对象,还是迭代器对象

a.可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象

 1 """
 2     下列数据类型都是可迭代的对象
 3 """
 4 # 字符串
 5 '123'.__iter__() 
 6 # 列表
 7 ['a','b','c'].__iter__()  
 8 # 字典
 9 {'a':1,'b':2,'c':3}.__iter__()
10 # 元组
11 (1,2,3).__iter__() 
12 # 集合
13 {'a',1,2,'b','c'}.__iter__() 
14 # 文件
15 f = open('a.txt','r',encoding='utf-8')
16 f.__iter__()
17 
18 
19 from collections import Iterable,Iterator    #导入模块
20 
21 # 使用内置 ininstancee( ,Iterable)查看,结果返回布尔值,True为正确
22 print(isinstance('abc',Iterable))
23 print(isinstance([],Iterable))
24 print(isinstance((),Iterable))
25 print(isinstance({'a':1},Iterable))
26 print(isinstance({1,2},Iterable))
27 f=open('a.txt','r')
28 print(isinstance(f,Iterable))
29 """
30 输出:
31 True
32 True
33 True
34 True
35 True
36 True
37 """

b.迭代器对象

 1 """
 2     只有文件是迭代器对象
 3 """
 4 
 5 # 只有文件本身是迭代器
 6 f.__next__()
 7 # 其它的,可迭代的对象执行__iter__方法后的结果就是迭代器
 8 a = '123'.__iter__()
 9 b = next(a)  #也可以这么写
10 a.__next__()
11 
12 
13 from collections import Iterable,Iterator    #导入模块
14 
15 #使用内置ininstancee( Iterator)查看,结果返回布尔值,True为正确
16 print(isinstance('abc',Iterator))
17 print(isinstance([],Iterator))
18 print(isinstance((),Iterator))
19 print(isinstance({'a':1},Iterator))
20 print(isinstance({1,2},Iterator))
21 f=open('a.txt','r')
22 print(isinstance(f,Iterator))
23 """
24 输出:
25 False
26 False
27 False
28 False
29 False
30 True
31 """

 c.迭代协议:

  对象有__next__

  对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身

  1 # 对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
  2 f=open('a.txt','r')
  3 f1=f.__iter__()
  4 
  5 print(f)
  6 print(f1)
  7 print(f is f1)
  8 """
  9 输出:
 10 <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'>
 11 <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'>
 12 True
 13 """
 14 
 15 # 可迭代对象list执行__iter__方法后,可以看到就是一个迭代器
 16 l=[]
 17 i=l.__iter__()
 18 
 19 print(i.__iter__())
 20 print(i)
 21 print(l)
 22 """
 23 输出:
 24 <list_iterator object at 0x02CE0310>
 25 <list_iterator object at 0x02CE0310>
 26 []
 27 """
 28 
 29 # 字典,之前的调用方式
 30 dic={'name':'merry','age':18,'height':'165'}
 31 print(dic.items())
 32 
 33 for k,v in dic.items():
 34     print(k,v)
 35 
 36 """
 37  输出:
 38  dict_items([('name', 'merry'), ('age', 18), ('height', '165')])
 39 name merry
 40 age 18
 41 height 165
 42 """
 43 
 44 # while循环+迭代器的调用方式
 45 dic={'name':'merry','age':18,'height':'165'}
 46 i=iter(dic)
 47 while True:
 48     try:
 49         k=next(i)
 50         print(k)
 51         print(dic[k])
 52     except StopIteration:
 53         break
 54 
 55 """
 56 输出:
 57 name
 58 merry
 59 age
 60 18
 61 height
 62 165
 63 """
 64 #for循环本身就是迭代调用
 65 dic={'name':'merry','age':18,'height':'165'}
 66 for k in dic: #i=iter(dic)  k=next(i)
 67     print(k)
 68     print(dic[k])
 69 
 70 """
 71 输出:
 72 name
 73 merry
 74 age
 75 18
 76 height
 77 165
 78 """
 79 
 80 # 列表的for循环迭代
 81 l=['a','b',3,9,10]
 82 for i in l:
 83     print(i)
 84 """
 85 输出:
 86 a
 87 b
 88 3
 89 9
 90 10
 91 """
 92 
 93 # 文件迭代器,可以直接for循环迭代
 94 with open('a.txt','r',encoding='utf-8') as f:
 95     for line in f:
 96         print(line.strip())
 97 """
 98 输出:
 99 1
100 2
101 3
102 4
103 5
104 """

d.总结:

  python中for循环内部使用的就是迭代的方式

  for循环在处理过程中,把可迭代对象和迭代器都经过执行iter方法变成迭代器,所以在for循环时无法判断是可迭代对象还是迭代器

  for循环自动执行try异常处理,for循环= while+迭代+try异常处理

5、迭代器的优点和缺点

优点:

  a.提供了一种不依赖下标的迭代方式

 1 l=[10000,2,3,4,5]
 2 
 3 i=iter(l)
 4 
 5 print(i)
 6 print(next(i))
 7 
 8 """
 9 输出:
10 <list_iterator object at 0x02708510>
11 10000
12 """

  b.就跌迭代器本身来说,更节省内存

缺点:

  a. 无法获取迭代器对象的长度

  b. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退

 1 f=open('a.txt',encoding='utf-8')
 2 
 3 for line in f.readlines():
 4     print(line.strip())
 5 
 6 print(next(f))
 7 """
 8 输出:
 9 1
10 Traceback (most recent call last):
11 2
12   File "D:/python/s17/day04/迭代器.py", line 290, in <module>
13 3
14 4
15     print(next(f))
16 5
17 StopIteration
18 """
19 
20 f=open('a.txt',encoding='utf-8')
21 for line in f:
22     print(line.strip())
23 """
24 输出:
25 1
26 2
27 3
28 4
29 5
30 """

6、补充,枚举函数enumerate(),实际也是迭代器

 1 l=[10000,2,3,4,5]
 2 
 3 i=enumerate(l)
 4 
 5 print(next(i))
 6 print(next(i))
 7 """
 8 输出:
 9 (0, 10000)
10 (1, 2)
11 """
原文地址:https://www.cnblogs.com/zhangmeixia/p/6895107.html