哪个更痛苦,努力还是后悔?
前方高能--迭代器
1函数名的使用以及第一类对象.
2.闭包
3.迭代器
一. 函数名的运用
函数名的内存地址,但他是一个特殊的变量,与括号配合可以执行函数的变量.
1.函数名的内存地址
def func(): print('呵呵') print(func)
# 结果
<function func at 0x0588C618>
2.函数名可以赋值给其他变量.
def func(): print('呵呵') print(func) a = func # 把函数当成一个变量赋值给另一个变量. a() # 函数调用func()
3.函数名可以当作容器类的元素.
def func1(): print('哈哈') def func2(): print('哈哈') def func3(): print('哈哈') def func4(): print('哈哈') lst = [func1,func2,func3,func4] for i in lst: i()
4,函数名可以当作函数的参数,
def func(): print('吃了吗') def func2(fn): print('我是func2') fn() # 执行传递过来的fn func2(func) # 把函数func当成参数传递给func2的参数fn
5,函数名可以作为函数的返回值
def func_1(): print('这里是函数1') def func_2(): print('这里是函数2') print('这里是函数1') return func_2 fn = func_1() #执行函数1, 函数1返回的函数2, 这是fn指向的就是上面函数2 fn() # 执行上面返回的函数.
二. 闭包
什么是闭包? 闭包就是内层函数,对外层函数(非全局)的变量的引用,叫闭包.
def func1(): name = 'alex' def func2(): print(name) # 闭包 func2() func1() # 结果: alex
我们可以使用__closure__来检测函数是否闭包,使用函数名.__closure__返回cell就是闭包,返回None就不是闭包.
def func1(): name = 'alex' def fucn2(): print(name) #闭包 func2() print(func2.__closure__) func1()
问题,如果在函数外边调用内部函数呢?
def outeer(): name = 'alex' # 内置函数 def inner(): print(name) return inner fn = outer() # 访问外部函数,获取到内部函数的函数地址. fn() # 访问内部函数
那如果多层嵌套呢? 很简单,只需要一层一层的往外层返回就行了.
def func1(): def func2(): def func3(): print('嘿嘿') return func3 return func2 func1()()()
由它我们可以引出闭包的好处,由于我们在外界可以访问内部函数,那这个内部函数访问的时间和机制不一定了,因为在外部,我可以选择在任意的时间去访问内部函数,这个时候,想一想,我们之前说过,如果一个函数执行完毕,则这个函数中的变量以及局部命名空间空间中的内容都将会被销毁,在闭包中,如果变量被销毁了,那内部函数将不能正常执行,所以,python规定,如果你在内部函数中访问了外层函数中的变量,那么这个变量将不会被消亡,将会常驻在内存中,也就是说,可以保证外层函数中的变量在内存中常驻.
from urllib.request import urlopen def but(): content = urlopen('http://www.xiaohua100.cn/index.html').read() def get_content(): return content return get_content fn = but() # 这个时候就开始加载校花100的内容. # 后面需要用到这里面的内容就不需要在执行非常耗时的网络连接操作了 content = fn() # 获取内容 print(content) content2 = fn() # 重新获取内容, print(content2)
综上,, 闭包的作用就是让一个变量能够常驻内存,供后面的程序使用.
三. 迭代器
str,list,tuple,dict,set,可迭代对象,遵循了可迭代协议,
如果 对象中 有__iter__()函数,那么我们认为这个对象遵循可迭代协议,就可以获取到相应的迭代器,这里的__iter__是帮助我们获取到对象的迭代器,
我们使用__next__()来获取到迭代器中的元素.
s = '最近你变得很冷漠' c = s.__iter__() # 获取迭代器. print(c.__next__()) # 使用迭代器进行迭代,获取一个元素 最 print(c.__next__()) #近 print(c.__next__()) #你 print(c.__next__()) #变 print(c.__next__()) #得 print(c.__next__()) #很 print(c.__next__()) # 冷 print(c.__next__()) # 漠 print(c.__next__()) StopIteration
for 循环的机制:
for i in [1,2,3] print(i)
使用while循环+迭代器来模拟for循环
lst = [1,2,3] lst_iter lst.__iter__() while 1: try: it = lst_iter.__next__() print(it) except StopIteration: break
总结:
Iterable: 可迭代对象, 内部包含__iter__()函数
Iterator: 迭代器, 内部包含__iter__() ,同时包含__next__()
迭代器的特点:
1.节省内存,
2,惰性机制
3, 不能反复,只能向下进行
我们可以把要迭代的内容当成子弹,然后, 获取到迭代器__iter__(),就把子弹都装在弹夹中,
然后发射就是__next__()把每个字典(元素)打出来,也就是说,for循环的时候,一开始的时候是
__iter__()来获取迭代器,后面每次获取元素都是通过__next()来完成的,当程序遇到StopIteration将结束循环.