Python 闭包、迭代器和生成器

1, 函数名的应用,第一类对象
函数名可以像变量一样进行使用
(1)赋值
(2)作为list元素
(3)作为参数
(4)作为返回值

2, 闭包
内部函数访问外部函数的局部变量.
好处:
(1)安全
(2)常驻内存. 提高效率

name = "wusir"  # 变量写在全局是不安全的

def abc():
    global name
    name ="呵呵"
abc()

def func():
    name = "alex"   # 常驻内存  防止其他程序改变这个变量
    def inner():
        print(name)  # 在内层函数中调用了外层函数的变量,叫闭包, 可以让一个局部变量常驻内存
    return inner
ret = func()
ret()     # 执行的是inner()
ret()

 

# 闭包的好处

from urllib.request import urlopen
def but(): content = urlopen("http://www.h3c.com/cn/").read() def inner(): print("你好啊") # return content # 在函数内部使用了外部的变量 . 闭包 print(inner.__closure__) # 查看inner是否是闭包, 如果有东西就是闭包, 没东西None就不是闭包 return inner print("加载中........")
fn
= but() # 这个时候就开始加载校花100 的内容 # 后⾯需要⽤到这⾥⾯的内容就不需要在执⾏⾮常耗时的⽹络连接操作了 content = fn() # 获取内容 print(content) content2 = fn() # 重新获取内容 print(content2)

 

3, 迭代器
可迭代对象(Iterable):内部包含__iter__().
迭代器(Iterator): 内部含有__iter__() __next__()
str, list, tuple, set, dict
f, range

迭代器的特点:
(1)省内存
(2)惰性机制 (只有__next__()了才会执行)
(3)只能往下进行,不能回头

 

# 可迭代对象: str, list, tuple, set, f, dict
# 所有的以上数据类型中都有一个函数__iter__(), 所有包含了__iter__()的数据类型都是可迭代的数据类型 Iterable

 

# dir()来查看一个对象,数据类型中包含了哪些东西

lst = [1,2,3]   # list
print(dir(lst))
s = "王尼玛"
print("__iter__" in dir(s))     #True
print("__iter__" in dir(lst))    #True
print("__iter__" in dir(123))  #False

 

 

#list是一个Iterable.可迭代的

lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] #获取迭代器 it = lst.__iter__() # 迭代器往外拿元素. __next__() print(it.__next__()) # 皇阿玛 print(it.__next__()) # 皇额娘 print(it.__next__()) # 容嬷嬷 print(it.__next__()) # 紫薇 print(it.__next__()) # 迭代到最后一个元素之后. 再进行迭代就报错了 # lst = ["皇阿玛", "皇额娘", "容嬷嬷", "紫薇"] # 模拟for循环 it = lst.__iter__() while True: try: name = it.__next__() print(name) except StopIteration: # 拿完了 break lst = [1, 2, 3] from collections import Iterable # 可迭代的 from collections import Iterator # 迭代器 # isinstence(对象, 类型) 判断xx对象是否是xxx类型的 print(isinstance(lst, Iterable)) #True print(isinstance(lst, Iterator)) #False it = lst.__iter__() print(isinstance(it, Iterable)) # 判断是否是可迭代的 迭代器一定是可迭代的 print(isinstance(it, Iterator)) # 迭代器里面一定有__next__(), __iter__() print("__iter__" in dir(lst)) # 确定是一个可迭代的 print("__next__" in dir(lst)) # 确定不是一个迭代器 # f = open("01 今日内容大纲",mode="r", encoding="utf-8") # print(isinstance(f, Iterable)) # print(isinstance(f, Iterator))

 

迭代器的特点:
(1)省内存
(2)惰性机制
(3)只能往下进行,不能回头

lst = ["哈哈", "呵呵"]
it = lst.__iter__()
it.__next__()
print(it.__next__())
print("我要吃黄瓜")

 

生成器和生成器函数
生成器的本质就是迭代器

生成器的三种创建办法:
(1)通过生成器函数
(2)通过生成器表达式创建生成器
(3)通过数据转换

生成器函数:
函数中包含了yield的就是生成器函数
注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行

生成器表达式:
(结果 for 变量 in 可迭代对象 if 筛选)
取值:
1. __next__()
2. send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值
3. 可以for循环
4. list(g)

def func():
    print("我是周杰伦")
    yield "昆凌"     # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数
    print("我是王力宏")
    yield "李云迪???"
    print("我是笛卡尔积")
    yield "笛卡尔积是谁"
    print("你好啊")    # 最后一个yield之后如果再进行__next__() 会报错

g = func()   # 通过函数func()来创建一个生成器
print(g.__next__()) # 周杰伦
print(g.__next__()) # 王力宏
print(g.__next__()) # 笛卡尔积
print(g.__next__())

 

#return 直接返回结果. 结束函数的调用
# yield 返回结果.可以让函数分段执行

 

def func():
    yield 11
    yield 22
    yield 33
    yield 44

g = func()  # 拿到的是生成器. 生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环

for i in g:
    print(i)    # 本质上执行的是__next__()

it = g.__iter__()
while True:
    try:
        print(it.__next__())
    except StopIteration:
        break

 

#send

def func():
    print("大碴粥")
    a = yield "11"
    print(a)
    print("狗不理")
    b = yield "22"
    print(b)
    print("大麻花")
    c = yield "33"
    print(c)

g = func()
print(g.__next__()) #大碴粥 11
print(g.send(1))  #1 狗不理 22
print(g.send(2)) #2 大麻花 33
print(g.send(3)) #3 报错

# __next__() 可以让生成器向下执行一次
# send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个不能用send(). 最后一个也不要传值

 

 推导式 

 

1列表推倒式; 最终给你的是列表
# 语法 [最终结果(变量) for 变量 in 可迭代对象]

 

2字典推导式

dic = {"a":"b", "c":"d"}
# 把字典中的key:value互换 . {"b":"a", "d":"c"}
new_dic = {dic[key]:key for key in dic}
print(new_dic)

lst1 = ["alex", "wusir", "taibai", "ritian"]
lst2 = ['sb', "很色", "很白", "很牛"]
# {"alex":"sb", "wusir":"很色"}

dic = { lst1[i]:lst2[i] for i in range(len(lst1))} #用索引
print(dic)

 

3集合推导式

lst = ["马化腾", "马化腾", "王建忠", "张建忠", "张建忠", "张雪峰", "张雪峰"]

s = {i for i in lst}    # 集合推导式

 

 

posted @ 2018-07-18 20:23  BabyJoy❤️  阅读(157)  评论(0编辑  收藏  举报