day11 python之函数闭包、可迭代对象和迭代器

一、函数名的应用
1,函数名就是函数的内存地址,而 函数名() 就是运行这个函数
def func():
return

print(func) #返回一个地址

2,函数名可以作为变量。
def func1():
print(666)
f1 = func1
f2 = f1
f2() #就等于func1() 此时执行函数

3,函数名可以作为函数的参数。
def func1():
print(666)

def func2(x):
x()
func2(func1) #输出666 func1作为实参传进func2中,此时在func2中x()等于func1()


4,函数名可以当做函数的返回值。
def wraaper():
def inner():
print(666)
return inner
ret = wraaper() #执行函数wraaper(),得到返回值inner赋值给ret,这个inner是函数名
ret() #输出666,ret()等于inner()
(注意:这里要调用inner()只能是用ret(),因为inner()是wraaper()的嵌套函数,
在全局命名空间中并没有声明,所以直接用inner()不能执行,)


def func2():
print('in func2')

def func3(x):
print('in func3')
return x

f = func3(func2) #给func3传进一个参数func2,返回func2赋值给f
f() #f()等于func2()

 

5,函数名可以作为容器类类型的元素。
例子:
def f1():
print('f1')


def f2():
print('f2')


def f3():
print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()

 

例子:
def func1():
print('in func1')

def func2():
print('in func2')

def func3():
print('in func3')

def func4():
print('in func4')

l1 = [func1,func2,func3,func4]

#调用
for i in l1:
i()

像上面的函数名这种,成为第一类对象。
第一类对象(first-class object)指:
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
(如果不明白,那就记住一句话,就当普通变量用)


6、globals() locals()
globals() #返回全局变量的一个字典。
locals() #返回当前位置的变量的字典。
例如:
def func1():
a = 2
b = 3
print(globals()) #此时globals()在局部命名空间中,但也是返回全局命名空间的一个字典{'__name__': '__main__', '__doc__': None(后面还有一大推东西,省略)...}
print(locals()) #此时locals()在局部命名空间中,所以返回的是局部命名空间的一个字典{'b': 3, 'a': 2}
print(globals()) #此时globals()在全局命名空间中,返回全局命名空间的一个字典{'__name__': '__main__', '__doc__': None(后面还有一大推东西,省略)...}
print(locals()) #此时locals()在全局命名空间中,所以返回的是全局命名空间的一个字典{'__name__': '__main__', '__doc__': None(后面还有一大推东西,省略)...}
func1()
总结:
globals()无论在哪个命名空间,返回的都是全局命名空间的一个字典
locals()在哪个命名空间就返回哪个命名空间的字典

 


def func1():
a = 2
b = 3
def inner():
c = 5
d = 6
print(globals()) #{'__name__': '__main__', '__doc__': None(后面还有一大推东西,省略)...}
print(locals()) #{'c': 5, 'd': 6}
inner()
func1()

 


二、闭包
1、内层函数对外层函数的变量(非全局变量)的引用,并返回,这样该内部函数称为闭包函数。
(我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?
就把这个函数的名字返回就好了,这才是闭包函数最常用的用法)
def wraaper():
name = '鬼见愁'
def inner():
print(name)
return inner

f = wraaper()
f()


2、判断闭包函数的方法__closure__
1,是闭包就会返回(<cell at 0x0000022EC0EB7618: str object at 0x0000022EC0F642D0>,)
def wraaper():
name = '鬼见愁'
def inner():
print(name)
print(inner.__closure__)
return inner
f = wraaper()
f()

 


2,不是闭包就会返回None
name = '鬼见愁'
def wraaper():
def inner():
print(name)
print(inner.__closure__) # None
return inner
f = wraaper()
f()

 

name = '番薯'
def wraaper(n):
n = '番薯'
def inner():
print(n)
print(inner.__closure__) # cell at 0x000002AD93BF76D8
inner()
return inner
wraaper(name)


'''
闭包作用:
当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,局部名称空间,
如果这个函数内部形成了闭包,
那么他就不会随着函数的结束而消失。
'''
什么时候用到闭包?
例如:爬虫,装饰器
下面是一个爬虫的小案例:
from urllib.request import urlopen
def index():
url = "http://www.xiaohua100.cn/index.html"
def get():
return urlopen(url).read()
return get

xiaohua = index() # get
content = xiaohua() # get()
print(content.decode('utf-8'))


三、可迭代对象
for i in 'abc':
print(i)

for i in 123:
print(i) # 'int' object is not iterable

对象内部含有__iter__方法就是可迭代对象.
可迭代对象满足可迭代协议。

可迭代对象:str list dict,tuple,set,range()
dir() :返回一个列表,列表里面包含了传入的参数的属性、方法
s1 = 'strs'
print(dir(s1))

判断一个对象是否是可迭代对象:
第一个方法
dic = {'name':'alex'}
print('__iter__' in dir(s1))
print('__iter__' in dir(dic))


第二种方法
from collections import Iterable #判断是否为可迭代对象
from collections import Iterator #判断是否为迭代器

print(isinstance('alex',Iterable)) # True
print(isinstance('alex',Iterator)) # False

print(isinstance('alex',str)) # True
isinstance() 应用比type()更广泛,isinstance()不仅可以判断你是不是可迭代对象,
也可判断你是否迭代器,还可以判断你是什么类型的数据等等,而type()只能判断你是什么数据类型

 


四、迭代器
1、对象内部含有__iter__方法且含有__next__方法就是迭代器。
文件句柄是迭代器:
f = open('register', encoding='utf-8')
print('__iter__' in dir(f)) #True
print('__next__' in dir(f)) #True

字典是可迭代对象,不是迭代器。
print('__iter__' in dir(dict)) #True
print('__next__' in dir(dict)) #False


2、可迭代对象与迭代器的区别:
1,可迭代对象不能取值,迭代器是可以取值的。
(我们知道字典列表都是可迭代对象,为什么它们能取值呢?这是因为为了方便我们操作,我们设定了
索引(键)用来操作字典列表取值,如果没有人为为它们设置的索引(键),它们是不能取值的)
2, 迭代器非常节省内存。
3,迭代器每次只会取一个值。
4,,迭代器单向的,一条路走到头。


3、可迭代对象 --->(转化成)迭代器
lis = [1, 2, 3] # 可迭代对象
ite1 = lis.__iter__() # 迭代器 <list_iterator object at 0x0000027A183BFFD0>
ite1 = iter(lis) # 迭代器 <list_iterator object at 0x0000027A183BFFD0>
print(ite1)

4、迭代器如何取值? next一次,取一个值
print(ite1.__next__())
print(ite1.__next__())
print(ite1.__next__())

 

5、while循环模拟for循环机制
1,将可迭代对象转化成迭代器。
2,调用__next__方法取值。
3,利用异常处理停止报错。

s1 = 'abcdefg'
iter1 = s1.__iter__()
while 1:
try:
print(iter1.__next__())
except StopIteration:
break

 

猜你喜欢

转载自www.cnblogs.com/Zzbj/p/9495066.html
今日推荐