1、函数对象闭包
函数是第一类对象:函数的内存地址(即函数名)能够像一个变量值同样去使用ide
一、变量值能够被引用,例如 x = 1,y = x函数
def foo(): print('from foo') f = foo # 变量值(函数名)被引用
print(f) f()
二、变量值能够看成参数传给另一个函数url
def foo(): print('from foo') def bar(x): print(x) x() bar(foo) # 函数名看成参数传给另一个函数
三、变量值能够看成函数的返回值spa
def foo(): print('from foo') def func(x): return x f = func(foo) # 函数名看成函数的返回值
print(f)
四、变量值能够看成容器类型的元素code
def foo(): print('from foo') li = [foo, ] # 函数名看成列表的元素
print(li) li[0]() dic = {'1': foo} # 函数名看成字典的元素
print(dic) dic['1']()
2、函数嵌套对象
一、函数的嵌套定义:在函数内又定义了其余函数blog
def func(): def foo(): print('from foo') foo() x = 1
print(x) func()
二、函数嵌套调用:在一个函数内部又调用其余函数内存
# 比较四个数的大小
def max2(x, y): if x > y: return x else: return y def max4(a, b, c, d): res1 = max2(a, b) res2 = max2(res1, c) res3 = max2(res2, d) return res3 print(max4(1, 2, 3, 4))
# 计算圆的面积和周长
from math import pi def circle(radius, action): def cal_perimeter(): return 2 * pi * radius def cal_area(): return pi * (radius ** 2) if action == 1: res = cal_perimeter() elif action == 2: res = cal_area() return res res = circle(5, 1) print(res)
3、名称空间ci
一、定义:存放名字与值的内存地址绑定关系的地方
二、名称空间分为三大类:
内置名称空间:存放的是 Python 解释器自带的名字,Python 解释器的启动则产生,关闭则销毁
全局名称空间:建立的存储 “变量名与值的关系” 的空间,是在顶级定义的,Python程序执行时产生,程序执行完毕后则销毁
局部名称空间:在函数的运行中开辟的临时的空间,是在函数内部定义的,在函数调用时临时产生,调用完毕后则销毁
三种名称空间的加载顺序和取值顺序:
加载顺序:内置(程序运行前加载)-->全局(从上到下顺序加载进来的)-->局部(调用的时候加载)--->内置
取值:
当前在局部名称空间:局部 ---> 全局 ---> 内置
当前在全局名称空间:全局 ---> 内置
使用:全局不能使用局部的,局部的可使用全局的
4、做用域:就是做用范围
一、全局做用域
定义:包含内置与全局名称空间的名字
特色:在整个程序的任意位置都能被引用,全局有效
二、局部做用域
定义:包含局部名称空间的名字
特色:临时存活,只能在局部范围内生效
做用域关系是在函数定义阶段就已经固定死了,与调用位置无关!!
# 示范一:
def f1(): print(xxx) xxx = 111
def f2(): xxx = 222
# 无论f1在哪调用, 都是去找定义阶段的做用域关系,
# 与上面的xxx=222没有任何关系
f1() f2() # 执行结果:111
# 示范二:
xxx = 111
def f1(): ''' 函数定义阶段只检测语法, 不执行代码 这里先输出xxx, 先从局部找xxx, 找到了x=222可是却定义在了输出的下面 语法上这种写法是错误的 '''
print(xxx) xxx = 222 f1() # 执行结果报错
5、闭包函数
闭:封闭,指的是该函数定义一个内部函数
包:该内部函数包含了对外层函数做用域中变量的引用
def outter(): x = 1
def inner(): print("from inner", x) return inner f = outter() # 经过外部函数拿到了内部函数的地址
def foo(): print(f) f() foo()
为函数体传值的两种方式:
def foo():
print('hello %s' %name)
方式一:直接以参数的形式传入
def foo(name): print("hello %s" %name) foo('qiu') foo('qiu') foo('qiu')
这种方式要想屡次传值,每次都要手动添加参数
方式二:闭包含数
def outter(name): def foo(): print("hello %s" %name) return foo f = outter('qiu') f() f() f()
要想屡次传值只须要屡次调用函数便可
应用:获取一个网页的信息
# 解决方案一: 以参数的形式传入
def get(url): response = requests.get(url) if response.status_code == 200: print(response.text) # 要想屡次获取信息只能屡次传入
get('https://www.baidu.com') get('https://www.cnblogs.com')
# 解决方案二: 闭包函数无需屡次传入
def outter(url):
def get(): response = requests.get(url) if response.status_code == 200: print(response.text) return get baidu = outter('https://www.baidu.com') cnblogs = outter('https://www.cnblogs.com') # 要想屡次获取只需屡次调用
baidu() baidu() cnblogs()