一.今日主要内容总览(重点)
1.第一类对象->函数名=>变量名
(1)函数对象可以像变量一样进行赋值
(2)还可以作为列表的元素进行使用
(3)还可以作为返回值返回
(4)还可以作为参数进行传递 思想:函数名就是变量名
(不仅指向一块空间,还有自身的意义) 2.闭包->函数的嵌套
(1)内层函数对外层函数中的变量的使用
(2)好处:
1.保护变量不被侵害
2.让一个变量常驻内存 (3)如何通过代码查看一个闭包?
__closure__: 有东西就是闭包,没东西就不是闭包 (4)迭代器=>固定的思路.for循环
一个数据类型中包含了__iter__函数表示这个数据是可迭代的
dir(数据):返回这个数据可以执行的所有操作 (5) 判断迭代器和可迭代对象的方案(野路子)
__iter__ 可迭代的
__iter__ __next__ 迭代器 (6)判断迭代器和可迭代对象的方案(官方)
from collections import Iterable, Iterator
isinstance(对象, Iterable) 是否是可迭代的
isinstance(对象, Iterator) 是否是迭代器 (7)模拟for循环
lst=[]
#拿迭代器
it=lst.__iter__()
while 1:
try:
it.__next__()
excep StopIteration:
break #特征:
为了保证安全,我们在内部调用
1. 省内存(生成器)
2. 惰性机制
3. 只能向前. 不能后退 作用:统一了各种数据类型的遍历 3.迭代器->固定的思路.for循环
for循环的底层意义
二.今日内容大纲
1.第一类对象
2.闭包
3.迭代器
三.内容详解
1.第一类对象
(1)
def fn():
print('我叫fn')
print(fn)#结果:<function fn at 0x0000025672D298C8>
(2)
def fn():
print('我叫fn')
fn()
print(fn)
gn=fn #函数名可以进行赋值操作
print(gn)
gn()
'''
结果:
<function fn at 0x00000185567798C8>
<function fn at 0x00000185567798C8>
'''
(3)
def func1():
print('朱元璋')
def func2():
print('朱祁镇')
def func3():
print('徐洁')
def func4():
print('魏忠贤')
#操作一
lst=[func1,func2,func3,func4]#列表中什么都可以放,没有数据类型的限制
print(lst) #结果:朱元璋
#操作二:
lst[0]()
#操作三:
for el in lst: #el是列表中的每一项.
el() #拿到函数,执行函数
'''
结果:
朱元璋
朱祁镇
徐洁
魏忠贤
'''
(4)
def func1():
print('朱元璋')
def func2():
print('朱祁镇')
def func3():
print('徐阶')
def func4():
print('魏忠贤')
#操作一
lst=[func1(),func2(),func3(),func4()]
print(lst)
'''
结果:#总结:先调用每一个,因为没有返回值,只能是4个None
朱元璋
朱祁镇
徐洁
魏忠贤
[None, None, None, None]
'''
(5)
a=10
b=20
c=30
lst=[a,b,c]
print(lst)
'''
结果:
[10, 20, 30]
(6)
a=10
b=20
c=30
lst=[a,b,c]
print(lst)
'''
结果:
[10, 20, 30]
'''
#通过(4)和(5),发现变量和函数的操作是一样的,变量可能数据类型不同
#函数数据类型相同,变量的每次数据类型不一定相同
(6)#重点降临
def wrapper():
def inner():
print('我的天,还可以这样?')
print(inner) #<function wrapper.<locals>.inner at 0x0000021F4F929950>
# inner()
return inner
ret=wrapper()
print(ret) #<function wrapper.<locals>.inner at 0x0000021F4F929950>
(6-1)
def wrapper():
def inner():
print('我的天,还可以这样?')
print(inner) #<function wrapper.<locals>.inner at 0x0000021F4F929950>
# inner()
return inner
ret=wrapper()
print(ret) ##<function wrapper.<locals>.inner at 0x0000021F4F929950>
ret() #我的天,还可以这样?
#总结:在函数外部访问了函数内部的函数
'''
结果:
<function wrapper.<locals>.inner at 0x000001F1B8609950>
<function wrapper.<locals>.inner at 0x000001F1B8609950>
我的天,还可以这样?
'''
(7)
def wrapper():
def inner():
print('大冬瓜')
return inner #函数名可以向返回值一样返回#返回的是inner,也就是ret
ret=wrapper()
ret() #在函数外面访问了函数内部的函数
ret()
ret()
结果:
大冬瓜
大冬瓜
大冬瓜
(8)
def func1():
print('谢晋')
def func2():
print('杨士奇')
def func3():
print('徐渭')
def func4():
print('柳如是') #代理函数
#代理,也是装饰器的雏形
def proxy(a): #a就是变量,形参
#函数作为参数进行传递
#代理好处,可以加点东西
print('我是代理')
a()
print('代理执行完毕')
proxy(func1)
proxy(func3)
proxy(func4)
总结:函数名就是变量名
1.函数名可以像变量一样进行传递
2.函数名可以作为参数进行赋值操作
3.可以作为返回值返回
4.可以作为参数进行传递
2.闭包
(1)
def wrapper():
name='周杰伦'
def inner():
print(name)#在内层函数中,使用了外层函数的局部变量
inner()
wrapper()
'''
结果:
周杰伦
'''
(2)
def wrapper():
name='周杰伦'
def inner():
print(name)#在内层函数中,使用了外层函数的局部变量
return inner #返回函数名
ret=wrapper()
ret()
对比(1)和(2)的方式
闭包的优点:(定义:内层函数使用了外层函数的变量)
1.可以保护变量不被其他人侵害
2.保持一个变量常驻于内存
(3)#注意下面的注释
def wrapper():
name='周杰伦'
def inner():
print(name) #在内层函数中使用了外层函数的局部变量
return inner #返回函数名 ret=wrapper() #ret是一个内层函数
ret() #ret是inner,在外层执行的时机是不确定的,必须保证里面的name必须存在
(4)
#超级简易版爬虫
from urllib.request import urlopen #导入一个模块
def func():
#获取到网页中的内容,
content=urlopen('https://www.dytt8.net/').read()
return content.decode('gbk')
print(func())
(5)#把要反复打开的网站加载 到内存中,以便快速打开网站,缺点:耗内存
#提升缓存能力版
#解决缓存问题
# #超级简易版爬虫
from urllib.request import urlopen #导入一个模块 #苹果系统:干掉数字签名
# import ssl
# ssl._create_default_https_context=ssl._create_unverified_context() def func():
#获取到网页中的内容,当网速很慢的时候,反复的去打开这个网站,很慢
content=urlopen('https://www.dytt8.net/').read()
def inner():
return content.decode("gbk") #网页内容
return inner
# return content.decode('gbk')
print('开始网络请求')
ret=func() #网络请求已经完毕
print('网络请求完毕')
print('第一次',ret()[5])
print('第二次',ret()[5]) # print('第一次',ret())
# print('第二次',ret())
3.迭代器
(1)
s='今天下午考试'
for c in s:
print(c) #主要讨论:什么是可迭代,什么是不可迭代的?
'''
结果:
今
天
下
午
考
试
'''
(2)
for c in '哼哼哈哈':
print(c)#正确 for c in 123:
print(c)#错误
(3)
dir() 可以帮助我们查看xxx数据能够执行的操作
print(dir(str)) #__iter__
print(dir(int)) #没有__iter__
print(dir(list)) #有__iter__
print(dir(dict)) #有__iter__
print(dir(bool)) #没有__iter__ for i in True:
print(i) #报错:'bool' object is not iterable
(4)
print(dir(range))
f=open('呵呵',mode='r',encoding='utf-8')
print(dir(f)) #正确,文件也是可迭代的
共性:所有带有__iter__的东西都可以进行for循环,带有__iter__东西就是可迭代对象
(5)
lst=['贾樟柯','李安','杨德昌','王家卫'] # print('__iter__' in dir(lst)) #判断迭代器是否在lst中,结果:True
it=lst.__iter__() #it是拿到的是迭代器
print(it) #列表的迭代地址:<list_iterator object at 0x0000026309647518> print(it.__next__()) #下一个
print(it.__next__()) #下一个
print(it.__next__()) #下一个
print(it.__next__()) #下一个 # print(it.__next__()) #报错:下一个报错,因为列表中只有4个值 StopIteration 停止迭代 it=lst.__iter__() #只能重新获取迭代器
print(it.__next__()) #下一个,又可以用了
总结
1.只能向下执行,不能反复
2.结束的时候会给我们扔来一个错误 StopIteration
3.整合所有的数据类型进行遍历(int,bool除外)#最大的特点
(6)超级重点
lst=['海尔兄弟','阿童木','葫芦娃','舒克贝塔','大风车']
#while循环模拟for循环 for el in lst:
it=lst.__iter__() #获取到迭代器0
while 1: #循环
try: #尝试
el=it.__next__() #拿数据
print(el)
except StopIteration: #出了错误,意味着数据拿完了
break #结束循环
总结:
1.节省内存
2.惰性机制
3.不能反复,只能向下执行
hello world!
(7)
官方通过代码判断是否是迭代器
借助于两个模块,Iterator迭代器,Iterable可迭代的
from collections import Iterator,Iterable
lst=[1,2,3]
print(isinstance(lst,Iterator)) #某某某是否是迭代器,False
print(isinstance(lst,Iterable)) #某某某是否是可迭代的类型,True it=lst.__iter__() #迭代器一定可迭代,可迭代的东西不一定是迭代器 print(isinstance(it,Iterator)) #某某某是否是迭代器,False
print(isinstance(it,Iterable)) #某某某是否是可迭代的类型,True
结果:
False
True
True
True
总结:有些地方还有待完善