day 10 函数名的运用,闭包,迭代器
函数名的本质
函数名本质上就是函数的内存地址
函数名的五种运用:
1、函数名是一个变量
def func(): print(666) print(func) # 函数的内存地址 <function func at 0x000002B6D2559AE8>
2、函数名可以当做变量赋值
def func(): print(666) f1 = func f2 = f1 f2()
3、函数名可以当做容器类数据类型的元素
def func1(): print(111) def func2(): print(222) def func3(): print(333) l1 = [func1, func2 ,func3] for i in l1: i()
4、函数名可以当做函数的参数
def func(x): # x == func1 x() print('in func') def func1(): print('in func1') func(func1)
5、函数名可以当做函数的返回值
def func(x): # x ---> func1 return x # func1 def func1(): print('in func1') ret = func(func1) # ret = func1 ret() # func1() func(func1)() # x() == func1()
满足3,4,5 函数名也称为第一类对象
闭包:
什么是闭包:
def func(): name = 666 print(111) def func1(): print(name) # 这就是闭包, 内层函数对外层函数(非全局)变量的引用 func1() func()
1,内层函数对外层函数(非全局)变量的引用。
2,闭包只存在于内层函数中。
3,函数都要逐层返回,最终返回给最外层函数。
def func(): name = 'alex' def inner(): print(name) return inner f = func() # f = inner f()
闭包的判断
f.__closure__[0].cell_contents 闭包引用的外部变量
def func(): name = 'alex' age = 19 def inner(): print(name) print(age) return inner f = func() # 定义f,因为f是闭包 # 获取闭包引用的外层变量,如果不是闭包则报错 print(f.__closure__[0].cell_contents) #固定用法 19 print(f.__closure__[1].cell_contents) # alex
闭包有什么用?
闭包:解释器执行程序时,如果遇到函数,随着函数的结束而关闭临时名称空间,但是!!!如果遇到闭包,有一个机制:那么闭包的空间不会随着函数的结束而关闭。
def wrapper(step): num =1 def inner(): nonlocal num num += step print(num) # 输出 4 7 10 13 16 return inner f = wrapper(3) j = 0 while j < 5: f() j += 1
闭包就是在内存中开一个空间,常贮存一些内容,以便后续程序调用
闭包的应用:
1、装饰器
2、爬虫
迭代对象:
iterable: 可迭代对象
内部含有__iter__方法的就是可迭代对象,遵循可迭代协议
s1 = 'barry' l1 = [1, 2, 3] print('__iter__' in dir(s1)) # True 是可迭代对象
可迭代对象不能直接取值(含索引的迭代对象除外) ,需要转换成迭代器才能取值
迭代器
迭代器:内部含有'__iter__'并且含有'__next__'方法的就是迭代器,遵循迭代器协议。
可迭代对象转换成迭代器:
可迭代对象.__iter__()
obj = iter(可迭代对象)
判断一个一个对象是否是迭代器(含iter,next)或迭代对象
方法一: 看__iter__ , __next__ 在不在dir() 里面
s1 = 'abcdefg' obj = iter(s1) # 将s1转换成迭代器 print('__iter__' in dir(s1)) # True print('__iter__' in dir(obj)) # True print('__iter__' in dir(s1) and '__next__' in dir(s1)) # False print('__iter__' in dir(obj) and '__next__' in dir(obj)) # True
方法二: isinstance(obj, Iterable/Iterator)
s1 = 'abcdefg' obj = iter(s1) # 将s1转换成迭代器 from collections import Iterable # 迭代对象 from collections import Iterator # 迭代器 print(isinstance(obj,Iterator)) # 判断obj是否为迭代器 True print(isinstance(obj,Iterable)) # 判断obj是否为可迭代对象 True print(isinstance(s1,Iterator)) # 判断obj是否为迭代器 False print(isinstance(s1,Iterable)) # 判断obj是否为可迭代对象 True
迭代器取值
s2 = [1, 2, 3] obj = iter(s2) print(obj.__next__()) # 方法一 print(next(obj)) # 方法二
type() isinstance()区别?
# type()只是判断该对象的数据类型
# isinstance()不仅可以判断该对象的数据类型,而且可以判断其他很多
迭代器的作用:
1、节省内存
2、惰性机制 (netx())一下,出一个值
3、一条路走到黑,不走回头路
While循环模拟for循环机制
l1 = [i for i in range(10)] obj = iter(l1) while 1: try: # 试一试,如果报错就执行下面的命令 print(next(obj)) except StopIteration: break