函数对象
# def func():
# print('from func')
#1、可以赋值
# f = func
# print(f)
# f()
#2、可以当作参数传给另外一个函数
# def foo(x):
# # print(x)
# x()
# foo(func)
#3、可以当作函数的返回值
# def foo(x):
# return x # 返回func函数的内存地址
# res=foo(func) # 当作foo函数的参数 传入函数的内存地址
# print(res)
#4、可以当作容器类型的元素
# l=[func,] #可以当作列表里面的元素,本质是内存地址存放在列表中
# print(l)
# l[0]() # 从列表找到函数内存地址 括号引用
函数嵌套
函数嵌套的调用
# 函数的嵌套调用
# 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(1919,2222,3423,789))
# 这个是把上面的比较两个参数大小的函数 嵌套到另一个函数里面 比较多个参数的大小
函数嵌套的定义
# 函数的嵌套定义
#例子1
# def f1():
# x=10
# def f2():
# print('from f2')
# f1()
# print(x) 变量定义在内部 外部访问不到
# print(f2) 变量定义在内部 外部访问不到
# 例子2
# def f1():
# x=10
# def f2():
# print('from f2')
# print(x)
# print(f2)
#
# f1()
名称空间与作用域
名称空间与作用域的关系是在函数定义阶段(扫描语法时)就确立的,与什么时候调用以及调用位置无关
名称空间
名称空间namespaces:存放名字与内存地址关系的地方
大致分为:
内置名称空间:存放内置的名字
生命周期:python解释器启动则产生,关闭则删除
全局名称空间:存放的是顶级的名字
生命周期:运行python文件则产生,运行完毕则销毁
局部名称空间:存放的是函数内的名字
生命周期:调用函数则产生,函数调用完毕则销毁
核心:
名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。
1、内置名称空间
伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,比如内建函数名
print(len)
>>><built-in function len> # built-in 内置
2、全局名称空间
伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,如下名字
x = 10
y = 20
if 1 > 0:
z = 30
with open('a.txt', mode='wt') as f:
a = 333
while True:
c = 444
3、局部名称空间
伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中
x = 10
def foo(m):
# m = 111
n=222
# foo(111)
核心:再次强调!
名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->全局名称空间->内置名称空间。
作用域
全局作用域:内置名称空间+全局名空间
特点:全局存活,全局有效
局部作用域:局部名称空间
特点:临时存活,局部有效
LEGB
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
全局作用域
全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用);
局部作用域
局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。
global
#global
# 案例1
# l = [] # 当全局变量是一个可变类型 可以从局部空间改变
# def func():
# # l.append(1111)
# #### 如果用global就能改 记住改是针对可变类型和重新定义不同
# l = [11,22,33] #这样相当于在局部新定义一个变量
#
# func()
# print(l)
# 案例2:
# x=111
# def func(): #无法在局部空间更改全局的不可变类型变量
#
# x =222
# func()
# print(x) #>>>111
#用 global 改
# x=111
# def func():
# global x # 改全局变量 声明
# x =222
# func()
# print(x) #>>>222
nonlocal
# nonlocal
# 只会在函数里面外层 不会去全局查找
x = 111
def f1():
x = 222
def f2():
nonlocal x # 改外层函数 不会到全局
x =333
f2()
print(x) # 这是打印的222 现在想把他内层33改为22
f1()
闭包函数
闭包函数的含义:
# 闭包函数
# 闭:指的是该函数是定义在函数内的函数
# 包:指的就是该函数引用了e层函数作用域的函数
闭包函数的定义:
def outter():
x = 111
def wrapper():
print(x)
return wrapper # 千万别加()
如何给函数传参?
# 方案一:直接用参数传
# def wrapper(x):
# print(x)
# wrapper(111)
# wrapper(222)
# wrapper(333)
#方案二:闭包函数
# def outter (x):
# def wrapper():
# print(x)
# return wrapper
# f1=outter(11111)
# f1()
#
# f2=outter(222)
# f2()