day4_python之名称空间与作用域、闭包函数、嵌套函数
一、名称空间与作用域
名称空间:存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方 内置名称空间:在python解释器启动时产生,存放一些python内置的名字 全局名称空间:在执行文件时产生,存放文件级别定义的名字 x=1 def func(): y=2 def f1():pass print import os class Foo: pass if x==1:z=3 del x 局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间 用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效 加载顺序:内置---》全局---》局部 优先掌握一:名字的查找顺序是:局部-》全局-》内置 # max=1 def foo(): max=2 # print(max) foo() print(max) x=0 def f1(): x=1 def f2(): x=2 def f3(): x=3 print(x) f3() f2() print('=f1========',x) f1() def func1(): print('from func1') def func1(): print('=====?>') func1() x=1 x=10 print(x)
1、什么是名称空间?
#名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
2、名称空间的加载顺序
python test.py #1、python解释器先启动,因而首先加载的是:内置名称空间 #2、执行test.py文件,然后以文件为基础,加载全局名称空间 #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
3、名字的查找顺序
局部名称空间--->全局名称空间--->内置名称空间 #需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例 # max=1 def f1(): # max=2 def f2(): # max=3 print(max) f2() f1() print(max)
二、作用域
作用域:作用的范围, 全局作用域:全局存活,全局有效:globals() max=1111111 def f1(): def f2(): def f3(): def f4(): # print(x) print(max) f4() f3() f2() f1() 局部作用域:临时存活,局部有效:locals() x=11111111111111111111111111111111111111111111 def f1(): x=1 y=2 def f2():pass # print(locals()) print(globals()) f1() print(locals() is globals()) print(locals()) print(dir(globals()['__builtins__'])) -------------------------------------------------- global nonlocal掌握 :global 修改全局的 x=1 def f1(): global x 明确声明x就是全局的x ,所以就会把全局的x=1,改成局部的x=2。 x=2 f1() print(x) ----------------------------------------------- l=[] def f2(): l.append('f2') 能直接把l的值改‘f2’,因为l是列表,列表是可变类型。 f2() print(l) ---------------------------------------------------- x=0 def f1(): # x=1 def f2(): # x=2 def f3(): # global x nonlocal x //修改的是函数内部正上方的那个X,所有x被修改成2.只在函数内部有效。 x=3 f3() # print(x) f2() print(x) f1() print(x) ----------------------------------------------------- 优先掌握二:作用域关系,在函数定义时就已经固定 ,与调用位置无关,在调用函数时,必须必须必须 回到函数原来定义的位置去找作用域关系 x=1 def f1(): def f2(): print(x) return f2 def foo(func): x=300000 func() res=f1() print(res) func=f1() print(func) x=10000000 func() x=10000000 def foo(func): x=300000000 func() #f2() x=10000000000000000000000 foo(f1()) # x=10000000000000000000000 # foo(f1()) x=1 def f1(): global x x=2 f1() print(x)
#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 内置模块的名字空间
三、global与nonlocal关键字
global nonlocal掌握 :global 修改全局的 x=1 def f1(): global x 明确声明x就是全局的x ,所以就会把全局的x=1,改成局部的x=2。 x=2 f1() print(x) ----------------------------------------------- l=[] def f2(): l.append('f2') 能直接把l的值改‘f2’,因为l是列表,列表是可变类型。 f2() print(l) ---------------------------------------------------- x=0 def f1(): # x=1 def f2(): # x=2 def f3(): # global x nonlocal x //修改的是函数内部正上方的那个X,所有x被修改成2.只在函数内部有效。 x=3 f3() # print(x) f2() print(x) f1() print(x)
四、闭包函数
1、什么是闭包?
#内部函数包含对外部作用域而非全局作用域的引用 #提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇 def counter(): n=0 def incr(): nonlocal n x=n n+=1 return x return incr c=counter() print(c()) print(c()) print(c()) print(c.__closure__[0].cell_contents) #查看闭包的元素
2、闭包的意义与应用
#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 #应用领域:延迟计算(原来我们是传参,现在我们是包起来) from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
大前提:作用域关系,在函数定义时就已经固定 ,与调用位置无关,在调用函数时,必须必须必须 回到函数原来定义的位置去找作用域关系 闭包函数: 1. 定义在函数内部的函数 2. 包含对外部作用域名字的引用,而不是对全局作用域名字的引用 那么该内部函数就称为闭包函数 x=1 def f1(): x=11111111111 def f2(): print(x) return f2 func=f1() x=1000 func() def foo(): x=12312312312312312312312312312312312313123 func() foo() def deco(): x=123123123123 def wrapper(): print(x) return wrapper func=deco() func() #闭包函数的应用:惰性计算 import requests #pip3 install requests 安装pip3 def get(url): return requests.get(url).text print(get('https://www.python.org')) print(get('https://www.python.org')) print(get('https://www.python.org')) print(get('https://www.python.org')) def index(url): # url='https://www.python.org' def get(): # return requests.get(url).text print(requests.get(url).text) return get python_web=index('https://www.python.org') baidu_web=index('https://www.baidu.com') python_web() baidu_web() name='egon' def index(url): x=1 y=2 def wrapper(): # x # y # return requests.get(url).text print(name) return wrapper python_web=index('https://www.python.org') # print(python_web.__closure__[0].cell_contents) print(python_web.__closure__) # print(python_web.__closure__[0].cell_contents) # print(python_web.__closure__[1].cell_contents) # print(python_web.__closure__[2].cell_contents)
五、嵌套函数
函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数 def bar(): print('from nbar') def foo(): #再调用一个函数的过程中,又去调用了另外一个函数 print('from foo') bar() foo() ----------------------------------------- 求两个值最大的函数 def max2(x,y): if x > y: return x else: return y def max4(a,b,c,d): 求四个值的最大值 res1=max2(a,b) 把a b 传进去会得到第一个结果 res2=max2(res1,c) 再调用一次,拿着这一次得到的结果在跟c进行比较 res3=max2(res2,d) return res3 得到res3最终的结果 print(max4(1,2,3,-1)) ------------------------------------------------- 函数的嵌套定义:在一个函数的内部,又定义另外一个函数 def f2(): print('from f2') def f1(): x=1 函数内部定义的名字,只是在函数被调用的时候生效。 # def f2() # print('from f2') f2() f1()