一 : 函数名的运用
1.函数名的内存地址
def func(): print("呵呵") print(func) 结果: <function func at 0x1101e4ea0>
2.函数名可以赋值给其他变量
def func(): print("呵呵") print(func) a = func # 把函数当成一个变量赋值给另一个变量 a() # 函数调用 func()
3.函数名可以当做容器类的元素
def func1(): print("呵呵") def func2(): print("呵呵") def func3(): print("呵呵") lst = [func1, func2, func3] for i in lst: i()
4.函数名可以当做函数的参数
5.函数名可以作为函数的返回值
def func_1(): print("这里是函数1") def func_2(): print("这里是函数2") print("这里是函数1") return func_2 fn = func_1() # 执行函数1. 函数1返回的是函数2, 这时fn指向的就是上面函数2 fn() # 执行上面返回的函数
二 : 闭包
闭包就是内层函数,对外层函数(非全局)的变量的引用
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() func1() 结果: alex
我们可以使用__closure__来检测函数是否是闭包,返回cell就是闭包,返回None就不是.
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,) func1()
在函数外边调用内部函数的方法:
def outer(): name = "alex" # 内部函数 def inner(): print(name) return inner fn = outer() # 访问外部函数, 获取到内部函数的函数地址 fn() # 访问内部函数
同样的,当有多层嵌套的时候:
def func1(): def func2(): def func3(): print("嘿嘿") return func3 return func2 func1()()()
使用闭包的好处 : 可以保证外层函数中的变量在内存中常驻,供后边的程序使用
三 : 迭代器
首先明确一个概念--可迭代对象,即str,list,tuple,dict,set,他们之所以是可迭代对象,是因为遵循了可迭代协议,通过dir()函数查看类中定义的所有方法,如果其中存在__iter__,那么这个类的对象就是可迭代对象.Iterable意为可迭代对象,Iterator意为迭代器,这是两个概念.
l = [1,2,3] l_iter = l.__iter__() from collections import Iterable from collections import Iterator print(isinstance(l,Iterable)) #True print(isinstance(l,Iterator)) #False print(isinstance(l_iter,Iterator)) #True print(isinstance(l_iter,Iterable)) #True
可以看到迭代器l执行了__iter__()方法之后获得了一个迭代器l_iter,可迭代对象不一定是迭代器,迭代器却一定是可迭代对象,那么迭代器是如何运行的呢,再看一段代码:
s = "我爱北京天安门" c = s.__iter__() # 获取迭代器 print(c.__next__()) # 使用迭代器进行迭代. 获取一个元素 我 print(c.__next__()) # 爱 print(c.__next__()) # 北 print(c.__next__()) # 京 print(c.__next__()) # 天 print(c.__next__()) # 安 print(c.__next__()) # 门 print(c.__next__()) # StopIteration
可以知道迭代器每次执行__next__()函数会返回可迭代对象的一个元素,当迭代完成再执行__next__()会报错StopIteration,知道迭代器的原理之后,我们回头再看for循环的原理:
for i in [1,2,3]: print(i) lst = [1,2,3] lst_iter = lst.__iter__() while True: try: i = lst_iter.__next__() print(i) except StopIteration: break
总结:
Iterable: 可迭代对象. 内部包含__iter__()函数
Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().
迭代器的特点:
1. 节省内存.
2. 惰性机制
3. 不能反复, 只能向下执行.