1.名称空间: 存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
1.全局命名空间:代码在运行伊始,创建的存储“变量名与值的关系”的空间
2.局部命名空间:在函数的运行中开辟的临时的空间叫做
3.内置命名空间:存放了python解释器为我们提供的本来就有函数的名字
三种命名空间之间的加载与取值顺序:
加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
取值顺序:
在局部调用:局部命名空间->全局命名空间->内置命名空间
注释:在全局无法查看局部的,在局部可以查看全局的,如下示例
max=1 def f1(): max=2 def f2(): max=3 print(max) f2() f1() print(max)
在全局调用:全局命名空间->内置命名空间
综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。
2.作用域
全局作用域,局部作用域。
全局作用域:全局名称空间,内置名称空间
局部作用域:局部名称空间
#1、作用域即范围 - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 - 局部范围(局部名称空间属于该范围):临时存活,局部有效 #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下 x=1 def f1(): def f2(): print(x) return f2 x=100 def f3(func): x=2 func() x=10000 f3(f1()) #3、查看作用域:globals(),locals() LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间 builtins 内置模块的名字空间
3.函数的嵌套
代码从上至下依次执行, 调用函数:函数里面从上至下依次执行。
print(111) def func1(): print(333) func2() print(666) def func2(): print(444) def func3(): print(555) func1() print(222)
>>>111 333 444 666 222
print(globals()) 全局名称空间:所有变量
print(locals()) 局部名称空间:所有变量
4.关键字
在基本的python语法当中,一个函数可以随意读取全局数据,但是要修改全局数据的时候有两种方法: 1 global 声明全局变量 2 全局变量是可变类型数据的时候可以修改
global:在局部空间内,声明一个全局变量
nonlocal: 在局部空间内改变一个全局变量。在局部作用域中,对上一级作用域(非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
b = 4 def add_b(): b = 42 def do_global(): nonlocal b b = 10 print(b) def dd_nonlocal(): global b b = b + 20 print(b) dd_nonlocal() print(b) do_global() print(b) add_b() print(b)
>>>10
>>>24
>>>10
>>>10
>>>24
5.函数名的应用
函数名是函数的名字,本质:变量,特殊的变量。 函数名() : 执行此函数。
1.单独打印函数名 : <function func1 at 0x0000000000872378>
2.函数名的赋值
def func2(): print(666) f = func2 print(f())
>>>666
3.函数名可以作为容器类数据的元素
def f1(): print(1211) def f2(): print(1222) l1 = [f1, f2,] for i in l1: i()
>>>1211
>>>1222
4.函数名可以作为参数
def f1(): print(666) def f2(x): # x = f1 x() # f1() f2(f1)
>>>666
5.函数名可以作为函数的返回值。
def f1(): print(666) def f2(x): # x = f1 return x ret = f2(f1) # f1 ret()
>>>666
6.闭包
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
闭包:就是内层函数对外层函数(非全局)变量的引用。 如何判断: 内层函数名.__closure__ cell 就是=闭包
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
from urllib.request import urlopen
'''
上面:提取 url文件
下面:作一个闭包返回函数调用
''' def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
应用领域:延迟计算(原来我们是传参,现在我们是包起来)
name = '老男孩' def wraaper2(n): # n = '老男孩' 相当于 def inner(): print(n) inner() print(inner.__closure__) # None wraaper2(name)
闭包:当函数开始执行时,如果遇到了闭包,他有一个机制,他会永远开辟一个内存空间,将闭包中的变量等值放入其中,不会随着函数的执行完毕而消失。