目录
2.如何判断可迭代(iterable) & 迭代器(iterator)
2)还可以通过isinstence()函数来查看⼀个对象是什么类型的
迭代器只能向前一个个地访问数据,已访问数据无法再次访问、遍历访问一次后再访问无数据
一.闭包
- 闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。(简单说就是在内层函数中调用了外层函数的变量)
# 用伪代码进行闭包格式的描述
def 外层函数(参数):
def 内层函数():
print("内层函数执行", 参数)
return 内层函数
内层函数的引用 = 外层函数("传入参数")
内层函数的引用()
#外层函数中的参数,不一定要有,据情况而定,但是一般情况下都会有并在内函数中使用到
1.闭包条件
在一个外函数中定义了一个内函数。
内函数里运用了外函数的临时变量。
并且外函数的返回值是内函数的引用。
如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
def func():
name = "alex" # 常驻内存防止其他程序改变这个变量
def inner():
print(name) # 在内层函数中调用了外层函数的变量,叫闭包, 可以让一个局部变量常驻内存
return inner
ret = func()
ret() # 执行的是 inner()
2) __closure__
使用函数名 __closure__ 查看是否为闭包,返回cell就是闭包. 返回None就不是闭包
2.闭包中内部函数对外部函数局部变量的修改
# fun是外部函数 a和b都是外函数的临时变量
def fun( a ):
b = 10 # a和b都是闭包变量
c = [a] #对应修改闭包变量的方法2
def inner():
# 内函数中想修改闭包变量
# 方法1 nonlocal关键字声明
nonlocal b
b += 1
# 方法二,把闭包变量修改成可变数据类型 比如列表
c[0] += 1
print(c[0])
print(b)
# 外函数的返回值是内函数的引用
return inner
if __name__ == '__main__':
demo = fun(5)
demo() # 6 11
#需要注意:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一
#个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量
def fun(x):
def inner(y):
nonlocal x
x += y
return x
return inner
a = fun(10)
print(a(1)) # 11
print(a(3)) # 14
3.闭包的作用
- 闭包就是让⼀个变量能够常驻内存. 供后面的程序使用.
二.迭代器
1.迭代器函数(iter和next)
1) 可迭代的__inter__() (iterable)
可迭代对象有:str, list, tuple, set,dict 可迭代对象可以进行for循环
所有以上的数据类型中都有一个函数__iter__(),也就是说所有包含了__iter__()函数的数据类型都是可迭代的数据类型(Iterable)
2) 迭代器__next__() (iterator)
Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误
#创建一个简单的迭代器
lst = [1, 2, 3, 4]
it = lst.__iter__() # 将lst列表生成迭代器
# 迭代器往外拿元素. __next__()
print(it.__next__()) # 1
print(it.__next__()) # 2
print(it.__next__()) # 2
print(it.__next__()) # 4
print(it.__next__()) # 迭代到最后一个元素之后. 再进行迭代就报错了 StopIteration
#使用for语句实现
lst = [1, 2, 3, 4]
it = lst.__iter__()
while True:
try:
name = it.__next__()
print(name)
except StopIteration: # 拿完了
break
2.如何判断可迭代(iterable) & 迭代器(iterator)
1) 通过dir()来查看一个对象数据类型中包含了哪些东西
2) 还可以通过isinstence()函数来查看⼀个对象是什么类型的
用法:
# dir()
lst = [1, 2, 3]
print(dir(lst))
# isinstance()
lst = [1, 2, 3]
from collections import Iterable # 可迭代的
from collections import Iterator # 迭代器
#isinstance(对象, 类型) 判断xx对象是否是xxx类型的
print(isinstance(lst, Iterable)) # True
print(isinstance(lst, Iterator)) # False
it = lst.__iter__()
print(isinstance(it, Iterable)) # True判断是否是可迭代的 迭代器一定是可迭代的
print(isinstance(it, Iterator)) # True迭代器里面一定有__next__(), __iter__()
print("__iter__" in dir(lst)) # True确定是一个可迭代的
print("__next__" in dir(lst)) # False确定不是一个迭代器
3.迭代器的特点
节约内存(循环过程中,数据不用一次读入,在处理文件对象时特别有用,因为文件也是迭代器对象)、不依赖索引取值、实现惰性计算(需要时再取值计算)
# 举例:用迭代器的方式访问文件
for line in open("test.txt"):
print(line) # 每次读取一行就输出一行,而不是一次性将整个文件读入,节约内存
-
迭代器只能向前一个个地访问数据,已访问数据无法再次访问、遍历访问一次后再访问无数据
lst = ["哈哈", "呵呵"]
it = lst.__iter__()
it.__next__()
print(it.__next__()) # 呵呵
print("我要吃黄瓜") # 我要吃黄瓜
print(it.__next__()) # StopIteration
lst = [1, 2, 3, "chi"]
i = iter(lst)
for el in i:
print(el) # 1 2 3 chi
for el in i:
print(el) # 再次执行没有输出
lst = [1, 2, 3, 4]
i = iter(lst) # 从list列表生成迭代器i
print(list(i)) # 将迭代器内容转换成列表,输出[1,2,3,4]
print(list(i)) # 将迭代器内容再次转换成列表 输出[]