一、函数名的应用及闭包
# 函数名的应用 及闭包 #1, 函数名就是函数对象在内存中的内存地址 def func(): print(6666) print(func) # <function func at 0x000002666B812E18> #2 函数名,可以作为变量 # a = 2 # b = a # c = b # print(b) def func1(): print(8888) f = func1 f2 = f f() # 8888 #3,函数名,可以作为函数的参数 def func2(): print(777,end=" ") def func3(x): print(999,end=" ") print(x,end=" ") x() print(func2) # <function func2 at 0x00000243C9718950> func3(func2) # 输出 999 <function func2 at 0x00000243C9718950> 777 #函数名,可以当作函数的返回值 print("\n"+"华丽的分隔线".center(68,'*')) def wrapper(): def inner(): print("in inner") return inner f=wrapper() f() # 函数名可以作为容器类型元素 def foo(): print("I am foo") def duck(): print("You are duck") def beat(): print("I like this beat") dic = {'foo':foo,'duck':duck,"beat":beat} dic['foo']() # I am foo dic['duck']() # You are duck dic['beat']() # I like this beat # 像上面函数名这种,称为第一类对象 # 第一类对象的特点 # 1, 可在运行期创建 # 2,可用作函数参数或返回值 # 3,可存入变量的实体 ## 不明白吗?那就记住一句话,就当普通变量用 # 闭包 # 内层函数 对 外层 函数的变量(非全局变量)的引用,这样就形成闭包,内层函数就叫闭包函数 def wrapper(): name = 'chris' def inner(): print(name) return inner func = wrapper() func() # chris # 判断闭包函数的常用方法: __closure__ def wrapper(): name = "LiMing" def inner(): print(name) print(inner.__closure__) # 输出的 __closure__有cell元素:是闭包函数 ,内部函数 被 一层外部函数,闭包 return inner wrapper() # (<cell at 0x000001FDE53D65B8: str object at 0x000001FDE70485E0>,) name = 'egg' def func2(): def inner(): print(name) print(inner.__closure__) # 输出的__closure__为None : 不是闭包函数 return inner f2 = func2() f2() # egg print("分道线".center(100,'#')) def wrapper(): money = 1000 def func(): name = 'baby' def inner(): # 内部函数 被 外部两层函数 闭包 print(name,money) print(inner.__closure__) # (<cell at 0x00000222CAB465B8: int object at 0x00000222CABE6B30>, <cell at 0x00000222CAB46618: str object at 0x00000222CAC086C0>) print('inner',inner) # inner <function wrapper.<locals>.func.<locals>.inner at 0x00000222CABD8AE8> return inner return func f = wrapper() i = f() # i() print("一线天".center(59,'$')) hobby = 'sing' def fn(n): # n = hobby n 是fn函数的局部变量 def inner(): print(n) print(n +"1") print(inner.__closure__) # (<cell at 0x000001DFEA006678: str object at 0x000001DFEA0C8768>,) return inner f = fn(hobby) print(f.__closure__[0].cell_contents) # 查看闭包的元素 f() # sing ''' 闭包的作用: 当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,局部名称空间, 如果这个函数内部形成了闭我,那么他就不会随着函数的结束而结束。 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 #应用领域:延迟计算(原来我们是传参,现在我们是包起来 ''' from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
二、迭代器:
# 可迭代对象 内部 有 __iter__ 方法 # lis = [1,3,5,10] # # print(dir(lis)) # print("__iter__" in dir(lis)) # 什么是迭代器? # 对象内部含有__iter___方法且含有__next__方法, 就是迭代器 # f = open('register',encoding='utf-8') # print(f) # print("__iter__" in dir(f)) # print("__next__" in dir(f)) # # print("__iter__" in dir(dict)) # print("__next__" in dir(dict)) # print(dir(f)) # 判断一个对象是否可迭代对象: # 第一个方法 dic = {'name':'chris'} s1 = "hello world" print('__iter__' in dir(dic)) # True print("__iter__" in dir(s1)) # True # 第二种方法 # from collections import Iterable # from collections import Iterator # print(isinstance(s1,Iterable)) # True 字符串是可迭代对象 # print(isinstance(s1,Iterator)) # False 字符串不是迭代器 # print(isinstance(s1,str)) # True # isinstance()方法 vs type()方法 # isinstance()可以判断对象 ,所从属的所有对象类别 ,而type()方法,仅判断 基本数据类型 # dir()方法,获取指定对象的所有方法名,将方法名以字符串类型,保存在一个列表中返回。 # 什么是迭代器? 迭代器,从表象上来说,就是具有 __iter__ 和 __next__方法的对象。 # 常见的迭代器,比如说,打开文件时,产生的文件句柄 fhandler = open("register",encoding='utf-8') print(fhandler) # <_io.TextIOWrapper name='register' mode='r' encoding='utf-8'> # 验证 文件句柄 是否具有 __iter__ 和 __next__ 方法 print( "__iter__" in dir(fhandler)) # True print( "__next__" in dir(fhandler)) # True # 验证 dict 类型 ,是不是迭代器? print('__iter__' in dir(dict)) # True 具有这个方法,表示是可迭代对象 print('__next__' in dir(dict)) # False # 可见 dict 类型,不是迭代器,它仅仅是一个可迭代对象。 # 另外一种判定方法: from collections import Iterator print(isinstance(fhandler,Iterator)) # True 是迭代器 # 可迭代对象 vs 迭代器 # 可迭代对象不能取值 ,迭代器是可以取值的。 # 可迭代对象 ---》 (转化成)迭代器 lis = [1,3,5] # 可迭代对象 ite1 = lis.__iter__() print(ite1) # <list_iterator object at 0x00000164B0C784E0> 列表迭代器对象 ite2 = iter(lis) # <list_iterator object at 0x000001D4D0B451D0> 列表迭代器对象 print(ite2) # 总结 : 调用可迭代对象的__iter__()方法,或者用iter(iterable)方法,把迭代对象传参进去 # 迭代器如何取值呢? next 一次,取一个值 # print(ite2.__next__()) # 1 # print(ite2.__next__()) # 3 # print(ite2.__next__()) # 5 # print(ite2.__next__()) # StopIteration 当手动从迭代器,取值,取完了,还取,抛出异常 # 迭代器的特点: # 1,可迭代对象不能取值,迭代器是可以取值的 # 2, 迭代器非常节省内存 # 3, 迭代器每一次只会取一个值 # 4,迭代器单向的,一条路走到头 # 用 while 循环 模拟 for 循环: # 1,将可迭代对象转化成迭代器 # 2,调用__next__方法取值 # 3,利用异常处理停止报错 # l = [11,12,13,14,15] # iter_l = iter(l) # while 1: # try: # print(iter_l.__next__()) # except StopIteration: # break