一 函数
- 作用:是对代码块进行封装和定义
- 形式:def func():
函数体
- 函数参数的位置关系:位置参数 > *args > 默认值参数 > **kwargs
- 函数参数的传递:func(*[1,2,3],**{1:2,3:5})类似解包的方式打散传递。
- 函数的命名空间:
1. 全局命名空间--> 我们直接在py⽂文件中, 函数外声明的变量量都属于全局命名空间
2. 局部命名空间--> 在函数中声明的变量量会放在局部命名空间
3. 内置命名空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
加载顺序:内置——>全局——>局部
取值顺序:局部——>全局——>局部
nonlocal 声明内部函数中局部变量 global 声明内部函数变量为全局变量 这两个一般都不用。
二 闭包
A.函数名相关知识
- 函数名是一个特殊的变量,存放的是函数的地址,加一个括号就可以执行函数了。
- 函数名可以赋值给其他变量
-
函数名可以当做容器类的元素
-
函数名可以当做函数的参数
def func(): print("吃了了么") def func2(fn): print("我是func2") fn() # 执⾏行行传递过来的fn print("我是func2") func2(func) # 把函数func当成参数传递给func2的参数fn
5.函数名可以作为函数的返回值
def func(): print("吃了了么") def func2(): print("我是func2") return func fn = func2() #fn指向func()函数的地址 fn()
B.闭包
定义:内存函数对外层函数(非全局变量)变量的引用。
def func(): a = 10 print("吃了了么") def func2(): print(a) print("我是func2") return func2 fn = func() fn() print(fn.__closure__)#(<cell at 0x019FD530: int object at 0x5E9FE3A0>,)
闭包的作用:由它我们可以引出闭包的好处. 由于我们在外界可以访问内部函数. 那这个时候内部函 数访问的时间和时机就不一定了, 因为在外部, 我可以选择在任意的时间去访问内部函数. 这个时候想想我们之前说过, 如果一个函数执行完毕. 则这个函数中的变量以及局部命名 空间中的内容都将会被销毁. 在闭包中如果变量被销毁了. 那内部函数将不能正常执⾏所以python规定. 如果你在内部函数中访问了外层函数中的变量. 那么这个变量将不会消亡. 将会常驻在内存中. 也就是说. 使⽤用闭包, 可以保证外层函数中的变量在内存中常驻. 这样做 有什么好处呢? 非常⼤大的好处. 一个关于爬⾍虫的代码:
from urllib.request import urlopen def but(): content = urlopen("http://www.xiaohua100.cn/index.html").read() def get_content(): return content return get_content fn = but() # 这个时候就开始加载校花100的内容 content = fn() # 获取内容 print(content) content2 = fn() # 后⾯面需要⽤用到这⾥里里⾯面的内容就不不需要在执⾏行行⾮非常耗时的⽹网络连接操作了了 print(content2)# 重新获取内容
C 迭代器
回顾:之前学过的可迭代对象,set、tuple、list、str、dict等
通过dir方法查看函数类中的方法可以确定是否为可迭代的,如果含有__iter__方法的就说明是个可迭代的对象。
print(dir(range))#'__iter__' print(dir(list))
还有一种方法查看:
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
for 的循环机制
lis = '我爱你祖国' c = lis.__iter__() #拿到一个迭代器 print(c.__next__())#我 print(c.__next__())#爱 print(c.__next__())#你 print(c.__next__())#祖 print(c.__next__())#国 print(c.__next__()) #StopIteration
# for i in '我爱你祖国': # print(i) lis = '我爱你祖国' c = lis.__iter__() #首先拿到一个迭代器 while 1: try: m = c.__next__() print(m) except StopIteration: break
D 总结
- Iterable: 可迭代对象. 内部包含__iter__()。
- 函数Iterator: 迭代器. 内部包含__iter__() 同时包含__next__().
- 迭代器的特点: 1. 节省内存. 2. 惰性机制 3. 不能反复, 只能向下执行.
我们可以把要迭代的内容当成子弹. 然后呢. 获取到迭代器__iter__(), 就把子弹都装在弹夹中. 然后发射就是__next__()把每⼀个子弹(元素)打出来. 也就是说, for循环的时候. 一开始的 时候是__iter__()来获取迭代器. 后面每次获取元素都是通过__next__()来完成的. 当程序遇到 StopIteration将结束循环.