过了元旦,加油鸭,冲鸭!!!
闲话不说,开始今日份学习整理。
今日目录,今天的学习内容不是很多!
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循环机制