day7-基础函数的学习(二)
过了元旦,加油鸭,冲鸭!!!
闲话不说,开始今日份学习整理。
今日目录,今天的学习内容不是很多!
1.函数名的运用
2.闭包(重要)
3.迭代器(重要)
开始今日份总结
1.函数名的运用
1.1函数名是一个特殊的变量
def func(): print(666) print(func) #结果 <function func at 0x000001C2D44E7F28> #返回函数的内存地址
1.2函数名可以当做变量赋值
def func(): print(666) func2 = func f1 = func2 f2 = f1 f3 = f2 print(f3) #结果,返回函数的内存空间 <function func at 0x0000020FA58B7F28>
1.3函数名可以当做容器类数据类型的元素
def func1(): print('func1') def func2(): print('func2') def func3(): print('func3') li =[func1,func2,func3] for i in li: i() #这样就可以一个一个的去调用函数了
1.4函数名可以当做函数的参数
def func(x): x() print('in func') def func1(): print('in func1') func(func1) #结果 in func1 in func
1.5函数名可以当做函数的返回值
def func(x): # x ---> func1 return x # func1 def func1(): print('in func1') ret = func(func1) # func1 ret() #结果 in func1
2.闭包(重要)
定义:
- 内层函数对于外层函数(非全局)变量的引用
- 闭包值存在于内层函数内
- 函数都要逐层返回,最终返回最外层的函数
- (个人理解)在函数外部可以调用函数内部,同时可以使用内部的值
闭包的确定
#不是闭包 name = 'test' def func1(): def inner(): print(name) return inner() f = func1() print(f.__closure__[0].cell_contents) #结果 AttributeError: 'NoneType' object has no attribute '__closure__' #表示函数内没有闭包的参数 #是闭包 # 闭包 def func(): age =18 name ='test' def inner(): print(age) print(name) return inner f = func() # 获取闭包引用的外层变量 print(f.__closure__[0].cell_contents) print(f.__closure__[1].cell_contents) #结果 18 test
闭包的用法
需求,输入一个数,连续自加这个数五次,有可能会写成这样
def func(step): sum = 1 sum += step print(sum) i =0 while i <5: func(3) i+=1 #结果 4 4 4 4 4
闭包:解释器执行程序时,如果遇到函数,随着函数的结束而关闭临时名称空间,但是!!!
如果遇到闭包,有一个机制:那么闭包的空间不会随着函数的结束而关闭。
重新写一下上面这个需求
def func(step): sum1 = 1 def inner(): nonlocal sum1 sum1 += step print(sum1) return inner i =0 f =func(3) while i <5: f() i+=1 #结果 4 7 10 13 16
需要注意的是,如果将f =func(3)放入下面循环内部,就会发现打印的都是4,原因呢,就是生产了五个闭包,每个闭包执行了一次。
闭包的常用使用环境
- 装饰器
- 爬虫的一些使用环境(对一个网页重复抓取,之前抓取的内容已经放在内存中)
3.迭代器(重要)
3.1可迭代对象
常用可迭代对象为:str list tuple set range() 文件句柄
可迭代对象:内部含有__iter__方法的就是可迭代对象,遵循可迭代协议,可迭代对象不能直接取值
判断是否是可迭代对象
# 方法一:
s1 = 'barry'
# print('__iter__' in dir(s1))
# print('__iter__' in dir(range(10)))
3.2迭代器
迭代器:内部含有'__iter__'并且含有'__next__'方法的就是迭代器,遵循迭代器协议。
可迭代对象转化成迭代器
可迭代对象.__iter__() 或者 iter(可迭代对象)
s1 = 'abcd' obj = iter(s1) print(obj) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) print(obj.__next__()) # 一个next 对应一个值,一一对应。 #结果 a b c d print(obj.__next__()) StopIteration
判断
一个对象是是迭代器
#方法一:判断一个对象内有没有指定的方法 li =[1,2,3,4] obj = iter(li) print('__iter__'in dir(obj) and '__next__'in dir(obj)) #结果 True #方法二:引入其他模块,进行判断 from collections import Iterable from collections import Iterator li =[1,2,3,4] obj = iter(li) print(isinstance(obj,Iterable))#判断是否是可迭代对象 print(isinstance(obj,Iterator))#判断是否是迭代器 #结果 True True #这个也可以用于判断上面是否是可迭代对象
type() isinstance()区别?
type()只是判断该对象的数据类型
isinstance()不仅可以判断该对象的数据类型,而且可以判断其他很多
迭代器的作用:
1,节省内存.
2,惰性机制.
3, 一条路走到黑,不走回头路.
s2 = [1, 2, 3, 4, 5]
obj2 = iter(s2)
print(next(obj2))
print(next(obj2))
练习
# 练习 # 判断一个对象是否是可迭代对象,迭代器 # str list tuple set dict range() 文件句柄 # f = open('file',encoding='utf-8',mode='w') # print(isinstance(f,Iterator)) # s2 = [1, 2, 3] # # 将s2转化成迭代器 进行取值 # obj2 = iter(s2) # # print(obj2.__next__()) # print(next(obj2)) #while循环模拟for循环机制