一. 函数名的运用.
函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量.
1. 函数名的内存地址
def func(): print("呵呵") print(func) #结果: <function func at 0x1101e4ea0>
2. 函数名可以赋值给其他变量
def func(): print("呵呵") print(func) a= func # 把函数当成一个变量赋值给另一个变量 a() # 函数调用 func() #结果: #<function func at 0x000002BECECA1F28> #呵呵
3. 函数名可以当做容器类的元素
def func1(): print("呵呵") def func2(): print("呵呵") def func3(): print("呵呵") def func4(): print("呵呵") lst = [func1, func2, func3] #将相应函数名放进一个列表中 for i in lst: #对列表进行循环遍历 i() #调用相应函数 #结果: # 呵呵 # 呵呵 # 呵呵
4. 函数名可以当函数的参数
def func(): print("吃了么") def func2(fn): print("我是func2") fn() # 执行传递过来的fn print("我是func") func2(func) # 把函数func当成参数传递给func2的参数fn. #结果: # 我是func2 # 吃了么 # 我是func
5. 函数名可以作为函数的返回值
def func_1(): print("这里是函数1") def func_2(): print("这里是函数2") print("这里是函数3") return func_2 fn = func_1() # 执行函数1. 函数1返回的是函数2, 这时fn指向的就是上面函数2 fn() # 执行上面返回的函数 #结果: # 这里是函数1 # 这里是函数3 # 这里是函数2
二. 闭包
1. 什么是闭包?
闭包就是内层函数对外层函数(非全局)的变量的引用. 这就叫闭包
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() func1() # 结果: alex
可以使用__closure__来检测函数是否是闭包. 如果有返回值就是闭包,如果返回None就不是闭包.
def func1(): name = "alex" def func2(): print(name) # 闭包 func2() print(func2.__closure__) func1() #结果: # alex # (<cell at 0x00000213219D65B8: str object at 0x0000021321A67180>,)
2. 闭包的好处
由于我们在外界可以访问内部函数. 那这个时候内部函数访问的时间和时机就不⼀定了, 因为在外部, 我可以选择在任意的时间去访问内部函数. 如果⼀个函数执行完毕. 则这个函数中的变量以及局部命名空间中的内容都将会被销毁. 在闭包中. 如果变量被销毁了了. 那内部函数将不能正常执行. 所 以. python规定. 如果你在内部函数中访问了外层函数中的变量. 那么这个变量将不会消亡. 将会常驻在内存中. 也就是说. 使⽤用闭包, 可以保证外层函数中的变量在内存中常驻.
三 . 迭代器
可迭代对象: str, list, tuple, set, f, dict
所有的额以上数据类型中都含有一个函数__iter__(),所有保留__iter__()的数据类型都是可以迭代的数据类型. Iterable
这是查看⼀个对象是否是可迭代对象的第⼀种办法. 我们还可以通过isinstence()函数来查 看⼀个对象是什么类型的
dir()来查看一个对象,数据类型中包含了哪些东西
lst = [1,2,3] # list print(dir(lst)) #结果: #['__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'] lst = [1,2,3] # list s = "王xx" print("__iter__" in dir(s)) #判断__iter__函数是否在某一个数据类型中 print("__iter__" in dir(lst)) print("__iter__" in dir(123)) #结果: # True # True # False lst = [1, 2, 3] it = lst.__iter__() print(isinstance(it, Iterable)) # 判断是否是可迭代的 迭代器一定是可迭代的 print(isinstance(it, Iterator)) # 判断是否为迭代器, 迭代器里面一定有__next__(), __iter__() print("__iter__" in dir(lst)) # 确定是一个可迭代的 print("__next__" in dir(lst)) # 确定不是一个迭代器,因为__next__函数不在lst内 #结果: # True # True # True # False
如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议. 就可以获取到相应的迭代器. 这里的__iter__是帮助我们获取到对象的迭代器. 我们使⽤迭代器中的__next__()来获取到⼀个迭代器中的元素.
迭代器特点:
1. 节省内存
2. 惰性机制
3. 只能一直向前直行,不能反复