函数名的应用,闭包,迭代器
一. 函数名的应用
1. 函数名的内存地址
def f(): pass print(f) #结果为函数f的内存地址 <function f at 0x000001CC079097B8>
2. 赋值
def f(): print('hello,world') a = f #把函数赋值给a a() #函数调用,结果为 hello,world
3. 函数名可以当做容器类的元素
def f1(): return 'hello' def f2(): return 'world' def f3(): return 'better' def f4(): return 'python' lst1 = [f1, f2, f3, f4] lst2 = [f1(), f2(), f3(), f4()] print(lst1) #四个函数的内存地址列表 print(lst2) #四个函数的返回值列表 ['hello', 'world', 'better', 'python']
4. 函数名可以当函数的参数
def f(fn): fn() def g(): print('今天吃饭了吗') f(g) #把函数名作为参数,传给另一个函数
5. 函数名可以当返回值
def f1(): print('hello,world') return f2 def f2(): print('snowdreams') a = f1() #把函数f1的返回值f2赋值给a a() #a(),其实就是调用函数f2 ,结果为 snowdreams
二. 闭包
闭包就是内层函数, 对外层函数(非全局)的变量的引用.
def f1(): a = 10 def f2(): print(a) #引用了外层函数f1的局部变量a,是闭包 f2() f1() #10
可以使用__closure__来检测函数是否是闭包.使用函数名.__closure__返回cell就是闭包,返回None就不是闭包.
def f1(): a = 10 print(f1.__closure__) #结果为 None 不是闭包 def f2(): print(a) #引用了外层函数f1的局部变量a f2() print(f2.__closure__) #判断是否是闭包结果是 (<cell at 0x00000196FC15C7F8: int object at 0x00007FF9E778D540>,) 是闭包 f1() #10
闭包的好处: 1. 安全 ,只能在函数内部才可以更改值 2. 常驻内存,提高效率
三. 迭代器
可迭代对象: str, list, dict, set, tuple
可以用dir()查看类中所有定义好的方法,含有__iter__,那么这个类的对象就是一个可迭代对象.
li = [1,2,3,4,5,6,7] print(dir(li)) #含有__iter__, 表示li是可迭代的 # ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', # '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', # '__init__', '__init_subclass__', '__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']
可以进行for循环的东西都有__iter__,包括range也有. 还可以通过isinstence()函数来查 看一个对象是什么类型的.
__iter__是获取到对象的迭代器. 使用迭代器中的__next__()来获取到一个迭代器中的元素. isinstence(对象, 类型) 判断xx对象是否是xxx类型的.
li = [1,2,3,4,5,6,7] it = li.__iter__() #使用__iter__来获取列表li的迭代器 from collections import Iterable from collections import Iterator print(isinstance(li,Iterable)) #判断列表li是否可迭代 结果为 True print(isinstance(li,Iterator)) #判断列表li是否是迭代器 结果为 False print(isinstance(it,Iterable)) #判断it是否可迭代 结果为 True print(isinstance(it,Iterator)) #判断it是否是迭代器 结果为 True
lst = [1, 2, 3, 4,] it = lst.__iter__() #获取lst的迭代器 print(it.__next__()) #1 print(it.__next__()) #2 print(it.__next__()) #3 print(it.__next__()) #4 # print(it.__next__()) #取完了,没有值可取,会报错
#模拟for循环 lst = [1,2,3,4,5] it = lst.__iter__() while True: try: num = it.__next__() print(num) except StopIteration: #若出现StopIteration错误,就break. break
总结:
Iterable: 可迭代对象. 内部包含__iter__()函数
Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().
迭代器的特点: 1. 节省内存. 2. 惰性机制 3. 不能反复, 只能向下执行.
无限的我,现在才开始绽放,从东边的第一缕阳光到西边的尽头