python函数闭包的应用_python学习第10天----函数名应用、闭包、迭代器

1.函数名的应用

1)如果直接打印函数名,打印出的为函数的地址

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():print("你好,世界")print(func)

输出:

View Code

#可将函数赋值给一个变量,再通过该变量调用函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():print("你好,世界")

a=func

a()#通过变量,间接调用函数

输出:

你好,世界

View Code

#将一个函数赋值给另一个函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():print("你好,世界")defa():print("hello world")

a= func #函数被另一个函数赋值

a()

输出:

你好,世界

View Code

例:将函数名放入列表,循环列表,进而调用每一个函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deff1():print("英雄联盟")deff2():print("地下城勇士")deff3():print("QQ飞车")deff4():print("穿越火线")

lst=[f1,f2,f3,f4]for el inlst:

el()

输出:

英雄联盟

地下城勇士

QQ飞车

穿越火线

View Code

2)将函数名作为函数的参数(即可以把函数作为参数,传递给另一个函数)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffu(gun):

gun()defgun():print("hello world")

fu(gun)#将函数作为参数传递

输出:

hello world

View Code

3)将函数作为返回值返回

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():definner():print("啊哈哈哈哈哈")returninner

ret= func() #这里func()执行之后获取到的是inner函数

ret() #这里让inner函数执行

输出:

啊哈哈哈哈哈

View Code

2.闭包

闭包就是内层函数对外层函数(非全局)的变量的引用,叫做闭包

#闭包演示

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():

name= "张三"

definner():print(name) #内层函数调用外层函数中的变量,叫做闭包

returninner

ret= func() #这里func()执行之后获取到的是inner函数

ret() #这里让inner函数执行

输出:

张三

View Code

1)闭包特点:可以让一个局部变量常驻内存;因为内部函数有可能随时使用该变量,如上面的inner函数有可能随时使用name变量

2)闭包作用:对于定义在全局中的变量是不安全的(可在函数中通过global修改全局变量),如果使用闭包的方式定义了变量,只能在内部函数中修改,别的程序无法修改这个变量

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():

name= "张三"

definner():print(name) #常驻内存;防止其他程序改变该变量

definner_change():

nonlocal name

name= "李四"

return inner

View Code

3)闭包的好处

①在使用爬虫的时候,可将爬取的内容,常驻内存,下次爬取时,直接从内存中获取,而不需要再次爬取

例:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

from urllib.request importurlopendefbut():

content= urlopen("https://blog.51cto.com/egon09/1836763").read()defget_content():returncontentreturnget_content

fn= but() #这个时候就开始加载内容#后⾯需要⽤到这⾥⾯的内容就不需要在执⾏⾮常耗时的⽹络连接操作了

content = fn() #获取内容

print(content)

content2= fn() #重新获取内容

print(content2)

View Code

4)检测一个函数是否闭包,使用函数名_closure_ 若返回cell就是闭包,返回None就不是闭包

#检测闭包,返回cell,即返回了内容

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():

name= "张三"

definner():print(name) #常驻内存;防止其他程序改变该变量

print(inner.__closure__) #判断是否为闭包

returninner

ret= func() #这里func()执行之后获取到的是inner函数

ret() #这里让inner函数执行

输出:

(,)

张三

View Code

#如果没有闭包,返回None

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

deffunc():

name= "张三"

definner():print("未使用外部变量") #常驻内存;防止其他程序改变该变量

print(inner.__closure__) #判断是否为闭包

returninner

ret= func() #这里func()执行之后获取到的是inner函数

ret() #这里让inner函数执行

输出:

None

未使用外部变量

View Code

3.迭代器

1) 可迭代对象:字符串、列表、元组、字典、set集合、文件句柄;可迭代对象可使用for循环遍历

①dir()可用来查看一个对象,数据类型中包含了哪些东西

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = [1,3,5,6,9]print(dir(lst))

输出:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

View Code

#查看基本数据类型中是否有函数__iter()__

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = [1,3,5,6,9]

s= "我爱北京天安门"num= 3399dic= {'LOL':"英雄联盟",'DNF':"地下城勇士"}

tup= (20,34,21,2,5)

set= {1,2,2,3,4}print("__iter__" indir(lst))print("__iter__" indir(s))print("__iter__" indir(num))print("__iter__" indir(tup))print("__iter__" indir(set))

输出:

True

True

False

True

True

View Code

总结:如上数据类型,之所以可迭代是因为有一个内置含函数__iter__();所有包含了__iner__()的数据类型都市可迭代的数据类型 Iterable ; __iter__()的工作就是返回一个迭代器

2)迭代器操作

①获取迭代器:通过函数__iter()__

②迭代器往外获取元素:__neex__()

只能一个一个获取可迭代数据类型中的元素;当迭代到最后一个元素,继续往下迭代就会报错

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = ["九尾妖狐","远古巫灵","无双剑姬","惩戒之箭"]

it= lst.__iter__()print(it.__next__())print(it.__next__())print(it.__next__())print(it.__next__())print(it.__next__())

输出:

StopIteration

九尾妖狐

远古巫灵

无双剑姬

惩戒之箭

View Code

#模拟for循环,对可迭代对象遍历

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = ["九尾妖狐","远古巫灵","无双剑姬","惩戒之箭"]

it= lst.__iter__()whileTrue:try: #捕获异常

name = it.__next__()print(name)except StopIteration: #出现StopIteration错误,直接退出循环

break输出:

九尾妖狐

远古巫灵

无双剑姬

惩戒之箭

View Code

3)迭代器和可迭代对象是不一样的:

①存在__iter__说明是可迭代的,即是一个可迭代对象

②如果没有__next__说明绝对不是一个迭代器(迭代器中也有__iter__方法),有__next__不一定是一个迭代器

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = [2,6,8]print("__iter__" in dir(lst)) #是可迭代的

print("__next__" in dir(lst)) #不是迭代器

输出:

True

False

View Code

#判断一个实例是否为可迭代对象或者迭代器

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

lst = [1,3,5]from collections importIterablefrom collections importIterator#isinstance(xx,XX) 判断xx对象是否XX类型

print(isinstance(lst,Iterable))print(isinstance(lst,Iterator))

it= lst.__iter__()print(isinstance(it,Iterator))

输出:

True

False

True

View Code

总结:迭代器一定是可迭代的;迭代器中一定有__next__()方法和__iter__()方法

#注:文件句柄、range是一个迭代器;字符串、列表、元组等是可迭代的,但不是迭代器

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

from collections importIteratorfrom collections importIterable

with open("游戏",mode="r",encoding="utf-8") as f:print(isinstance(f,Iterable))print(isinstance(f,Iterator))

输出:

True

True

View Code

4)迭代器特点

①节省内存

②惰性机制

③不能反复,只能向下执行(只能从前往后走,不能从后往前走)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值