巨蟒python全栈开发-第11天 第一类对象 闭包 迭代器

一.今日主要内容总览(重点)

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

总结:有些地方还有待完善

上一篇:用Python来实现列举某个文件夹内所有的文件列表


下一篇:python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))