1.函数名的使用和第一类对象
函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数
函数对象可以像变量一样进行赋值,还可以作为列表的元素进行使用,可以作为返回值返回,可以作为参数进行传递
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("呵呵") def func4(): print("呵呵") lst = [func1, func2, func3] for i in lst: i()
4.函数名可以当作函数的参数
def func(): print("吃了么") def func2(fn): print("我是func2") fn() # 执行传递过来的fn print("我是func2") func2(func) # 把函数func当成参数传递给func2的参数fn.
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() # 执行上面返回的函数
2.闭包
闭包就是内层函数,对外层函数(非全局)变量的引用
通过代码查看一个闭包:
__closure__来检测是否闭包,返回cell就是闭包,返回none就不是闭包
检测闭包:
def func1(): a = 10 def func2(): return a func2() print(func2.__closure__) func1() #(<cell at 0x00000215A5977498: int object at 0x0000000076EC6D30>,) 这个就是闭包
在函数外部调用内部函数:
def outer(): def inner(): print('我是内部函数') return inner a = outer() # 访问外部函数, 获取到内部函数的函数地址 a() # 访问内部函数
# 我是内部函数
闭包的好处:
1.保护变量不被侵害
2.让一个变量常驻内存
下面的这个爬虫的代码就用到了闭包的好处
from urllib.request import urlopen def but(): content = urlopen("www.dytt.com").read() def get_content(): return content return get_content fn = but() # 这时就在加载内容了 #后面需要用到这里面的内容就不需要在执行非常耗时的网络连接操作了 c1 = fn() # 获取内容 print(c1) c2 = fn() # 重新获取内容 print(c2)
由它我们可以引出闭包的好处. 由于我们在外界可以访问内部函数. 那这个时候内部函数访问的时间和时机就不一定了, 因为在外部, 我可以选择在任意的时间去访问内部函数. 这个时候.如果⼀个函数执行完毕. 则这个函数中的变量以及局部命名空间中的内容都将会被销毁. 在闭包中. 如果变量被销毁了. 那内部函数将不能正常执行. 所以. python规定. 如果你在内部函数中访问了外层函数中的变量. 那么这个变量将不会消亡.将会常驻在内存中. 也就是说. 使用闭包, 可以保证外层函数中的变量在内存中常驻.
3.迭代器
Iterable: 可迭代对象.内部包含__iter__()函数
Iterator: 迭代器. 内部包含__iter__() 同时包含 __next__()
迭代器的特点:
1. 省内存
2. 惰性机制
3. 只能向前, 不能后退
判断迭代器和可迭代对象的方案
1. _iter_函数判断可迭代的, dir(数据):返回这个数据可以执行的所有操作
s = 'abc' print(dir(s)) # 打印对象中的方法和函数 print(dir(str)) # 打印类中声明的方法和函数
在打印结果中,寻找__iter__如果能找到. 那么这个类的对象就是一个可迭代对象
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__',
2. __iter__ , __next__ 迭代器
官方的判断迭代器的方法:
from collections immport Iterable ,Iterator isinstance(对象,Iterable)是否是可迭代的 isinstance(对象,iterator)是否是迭代器
l = [1,2,3] l_iter = l.__iter__() from collections import Iterable,Iterator print(isinstance(l,Iterable)) # True print(isinstance(l,Iterator)) # False print(isinstance(l_iter,Iterable)) # True print(isinstance(l_iter,Iterator)) # True
使用while模拟for循环:
迭代器每次通过__next__() 来完成的,当程序遇到StopIteration将结束循环
模拟for循环 lst= [] it = lst.__iter__() while 1: try: it.__next__() except StopIteration: break