一、函数名的应用,第一类对象
函数名可以像变量一样进行使用
1、赋值
#函数名的内存地址: def func(): print("紫薇") print(func) #结果: <function func at 0x0000017923B92F28> #函数名赋值给其他变量 def func(): print("紫薇") print(func) #函数的内存地址 a = func #把函数当成一个变量赋值给另一个元素 a() #函数调用func() #结果: <function func at 0x00000272341D2F28> 紫薇
2、作为容器类的元素
#函数名作为容器类的元素 def func1(): print("紫薇") def func2(): print("紫薇") def func3(): print("紫薇") def func4(): print("紫薇") lis = [func1,func2,func3,func4] for el in lis: el()
3、作为参数
函数名当作函数的参数 def func(): print("我想紫薇了!") def func2(fn): print("我也想紫薇!") fn() #执行传递过来的fn print("我很想紫薇!") func2(func) #把函数func当成参数传递给func2的参数fn #结果: 我也想紫薇! 我想紫薇了! 我很想紫薇!
4、作为返回值
#函数名作为函数的返回值 def func(): print("我是紫薇!") def func2(): print("我也是紫薇!") print("我才是紫薇!") return func2 fn = func() #执行函数func,函数func返回的是函数func2,这时的fn指向的就是上面函数 fn() #执行上面返回的函数 #结果: 我是紫薇! 我才是紫薇! 我也是紫薇!
二、闭包:内层函数对外层函数(非全局)的变量的引用的 作用。
内部函数访问外部函数的局部变量
def func1(): name = "紫薇" def func2(): print(name) #闭包 func2() func1() #结果: 紫薇 --------------------------------------------------------- 可以使用__closure__来检测函数是否时闭包。使用函数__closure__返回cell就是闭包,返回None就不是闭包 def func1(): name = "紫薇" def func2(): print(name) func2() print(func2.__closure__) func1() #结果: 紫薇 (<cell at 0x0000018F1A737498: str object at 0x0000018F1A732D40>,) #如何在函数外边调用内部函数 def outer(): name = "紫薇" def inner(): print(name) return inner fn = outer() fn() #结果: 紫薇 #函数的嵌套: def func1(): def func2(): def func3(): print("紫薇") return func3 return func2 func1()()() #结果:紫薇
由于我们在外界可以访问内部函数. 那这个时候内部函数访问的时间和时机就不一定了, 因为在外部, 我可以选择在任意的时间去访问内部函数. 这个时候. 想一想. 我们之前说过, 如果一个函数执行完毕. 则这个函数中的变量以及局部命名 空间中的内容都将会被销毁. 在闭包中. 如果变量被销毁了. 那内部函数将不能正常执行. 所 以. python规定. 如果你在内部函数中访问了外层函数中的变量. 那么这个变量将不会消亡. 将会常驻在内存中. 也就是说. 使⽤闭包, 可以保证外层函数中的变量在内存中常驻
好处:
1、安全
2、常驻内存,提高效率
实例:爬虫实例
from urllib.request import urlopen def but(): content = urlopen("http://www.youku.com/").read() def get_content(): return content return get_content fn = but() content = fn() print(content) content2 = fn() print(content2)
三、迭代器
1、可迭代对象(Iterable):内部包含__iter__().
#对的 s= "abcd" for el in s: print(el) #错的 for el in 123: print(el) 报错:TypeError: 'int' object is not iterable(整数类型对象 是不可迭代的. iterable表⽰可迭代的. 表⽰可迭代协议. )
dir()函数:查看类中定义好的所有方法。
s = "我是张无忌" print(dir(s)) #打印对象中声明的方法和函数 print(dir(str)) #打印类中声明的方法和函数 #在打印结果中,找到__iter__的话,那么这个类的对象就是一个可 迭代对象 #字符串中可以找到__iter__。在list,tuple,dict,set中查看: print(dir(tuple)) print(dir(list)) print(dir(open("alex.txt"))) #文件对象 print(dir(set)) print(dir(dict)) #能进行for循环的东西都有__iter__函数,包括range也有
isinstance()函数:isinstance(对象,类型)判断xxx对象是否是xxx类型的
lis = [1,2,3] lis_l = lis.__iter__() from collections import Iterable #可迭代的 from collections import Iterator #迭代器 # ininstance(对象,类型),#判断xxx对象是否是xxx类型的 print(isinstance(lis,Iterable)) #结果是True print(isinstance(lis,Iterator)) #结果是False print(isinstance(lis_l,Iterable)) #结果是True 判断是否是可迭代的,迭代器一定是可迭代的 print(isinstance(lis_l,Iterator)) #结果是True 迭代器里面一定有__next__(),__iter__() print("__iter__" in dir(lis)) #确定是一个可迭代的 结果是Ture print("__next__" in dir(lis)) #确定不是一个迭代器 结果是False f = open("文件.txt",mode="r",encoding="utf-8") print(isinstance(f,Iterable)) print(isinstance(f,Iterator))
2、迭代器(Iterator):内部包含__iter__() 、__next__()
s = "大明湖畔夏雨荷" s1 = s.__iter__() #获取迭代器 print(s1.__next__()) #使用迭代器进行迭代,获取一个元素 print(s1.__next__()) print(s1.__next__()) print(s1.__next__()) print(s1.__next__()) print(s1.__next__()) print(s1.__next__()) print(s1.__next__()) #报错:StopIteration
for循环机制:
for el in [1,2,3]: print(el)
使用while循环+迭代器来模拟for循环(重点掌握):
lis = [1,2,3] li_iter = lis.__iter__() while True: try: el = li_iter.__next__() print(el) except StopIteration: break
#我们可以把要迭代的内容当成⼦弹. 然后呢. 获取到迭代器__iter__(), 就把⼦子弹都装在弹夹 中.
然后发射就是__next__()把每⼀个⼦弹(元素)打出来. 也就是说, for循环的时候. ⼀开始的时候
是__iter__()来获取迭代器. 后⾯每次获取元素都是通过__next__()来完成的. 当程序遇到
StopIteration将结束循环
3、可迭代数据类型:str、list、tuple、set、dict
4、迭代器数据类型:f(文件)、range
5、迭代器的特点:
1、节省内存
2、惰性机制
3、不能返回,只能向下执行