函数的嵌套定义
概念:在一个函数内部定义另一个函数
为什么要有函数的嵌套定义
--1、函数fn2想使用fn1内部的局部变量,可以直接把fn2定义到fn1的内部,这样fn2就可以直接访问fn1内部的变量
--2、函数fn2就变成了fn1的局部变量(名)了,想要在外部调用fn2,可以把fn2函数对象作为fn1的返回值传出去
--3、在外部也可以用fn2同名的变量来接收fn1的执行结果(返回值是fn2),那么fn2就可以在外部被调用了
def outer(): print('outer run') a = 10 #普通变量,随着函数的调用而产生,结束而销毁 def inner(): #函数对象和普通变量一样,随着函数的调用而产生,结束而销毁 print('inner run') inner() #所以只能在函数的内部调用outer()
函数的嵌套调用
在函数内部调用其他函数,可以将复杂的问题简单化
def index(): func() print('index')def func(): print('func')index()# func# index
#当你要比较出四个数字中最大的数时#可以首先写一个比较两个数大小的函数#通过调用这个函数,达到比较四个数大小的目的def my_max(x,y): if x > y: return x return ydef my_max4(a,b,c,d): res1 = my_max(a,b) res2 = my_max(res1,c) res3 = my_max(res2,d) return res3print(my_max4(1,2,10,4))
名称空间
(就是存放变量名与其相应内存地址的地方)
存放的是变量名与变量值的内存地址得绑定关系的地方
要想访问一个变量的值 必须先去名称空间中拿到对应的名字 才能够访问变量的值
名称空间分为三类:
1.内置名称空间:python解释器提前给你定义好的名字(已经存放到内置名称空间中了)
len max min2.全局名称空间:文件级别的代码
x = 1if 1 ==1 :
y = 2 print(y) while True: z = 3 x,y,z都会放到全局名称空间 if for while 无论嵌套多少层 它们内部所创建的名字都是全局名称空间的 3.局部名称空间:函数体内创建的名字都属于局部名称空间 username
生命周期:
内置名称空间:只要python解释器已启动立马创建关闭python解释器的时候内置名称空间自动销毁
全局名称空间:只要你右键运行py文件会自动创建 py文件程序运行结束自动销毁
局部名称空间:函数被调用的时候自动创建 函数指向结束立即销毁(动态创建动态销毁)名称空间的查找顺序
名字的查找 (******)
1.需要先确定你当前在哪(大前提) 1.站在全局: 全局 >>> 内置 2.站在局部: 局部 >>> 全局 >>> 内置
函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)
作用域
作用域:就是变量(名字|对象)起作用的范围
四种作用域
Built-in:内置作用域,作用与所有文件的所有地方
Global:全局作用域,作用于当前文件的所有地方
Enclosing:嵌套作用域:作用于当前函数及内部嵌套的函数
Local:局部作用域:作用域当前函数内部
#注:1、不同作用域之间的名字不冲突,所以重名无所谓
2、每个作用域都优先使用自己作用域的名字,没有的话再找更高的名称空间的名字,
知道内置,还没有就报错
3、查找顺序:Local > Enclosing > Global > Built-in
# global 在局部修改全局的不可变数据类型# x = [] # 因为列表是可变类型x = 1 # 不可变类型username = 'jason'def func(): # x.append('嘿嘿嘿') global x,username # 修改全局变量 而不是创建局部名称空间 x = 999 username = 'egon'func()print(x)print(username)# nonlocal 局部修改局部def func(): x = 1 def index(): nonlocal x x = 2 index() print(x)func()
global:局部修改全局 如果想修改多个 逗号隔开
nonlocal:局部修局部 如果想修改多个 逗号隔开