python函数作用域与闭包_python函数名称空间与作用域、闭包
一、命名空間概念
1、命名空間(name space)
名稱空間是存放名字的地方。
若變量x=1,1存放在內存中,命名空間是存放名字x、x與1綁定關系的地方。
2、名稱空間加載順序
python test.py
#1、python解釋器先啟動,因而首先加載的是:內置名稱空間
#2、執(zhí)行test.py文件,然后以文件為基礎,加載全局名稱空間
#3、在執(zhí)行文件的過程中如果調用函數,則臨時產生局部名稱空間
3、名字的查找順序
局部名稱空間——》全局名稱空間——》內置名稱空間
需要注意的是:在全局無法查看局部的,在局部可以查看全局的,如下例:
# max=1
def f1():
# max=2
def f2():
max=3
print(max)
f2()
f1()
print(max)
"""
3
"""
max=1
def f1():
# max=2
def f2():
# max=3
print(max)
f2()
f1()
print(max)
"""
1
1
"""
二、作用域
python中一個函數就是一個作用域,局部變量放置在其作用域中;代碼定義完成后,作用域已經完成,作用域鏈向上查找。類似C#、Java中作用域{}。
不同變量的作用域不同就是由這個變量所在的命名空間決定的。
1、作用域即范圍
全局范圍(內置名稱空間與全局名稱空間屬于該范圍):全局存活,全局有效
局部范圍(局部名稱空間屬于該范圍):臨時存活,局部有效
2、作用域關系是在函數定義階段就已經固定的,與函數的調用位置無關,如下:
x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1())
"""
10000
"""
3、查看作用域
LEGB 代表名字查找順序:locals ——>enclosing(相鄰的上一級) ——>globals ——> __builtins__
locals 是函數內的名字空間,包括局部變量和形參
enclosing 外部嵌套函數的名字空間
globals 全局變量,函數定義所在模塊的名字空間
builtins 內置模塊的名字空間
n = 10
def fun1():
n = 20
print('func1',n)
def fun2():
n = 30
print('func2',n)
def func3():
print("func3",n) # locals沒有,先找相鄰上一級作用域
func3() # 30
fun2() # 30
fun1() # 20
依次輸出:func1 20? ;func2 30? ; func3 30
def func():
level = 'L1'
n = 33
print(locals())
def outer():
n = 44
level = 'L2'
print(locals(), n)
def inner():
level = 'L3'
print(locals(), n)
inner() # {'n': 44, 'level': 'L3'} 44
outer() # {'n': 44, 'level': 'L2'} 44
func() # {'n': 33, 'level': 'L1'}
輸出如下結果:
{'n': 33, 'level': 'L1'}
{'level': 'L2', 'n': 44} 44
{'level': 'L3', 'n': 44} 44
三、閉包函數
內部函數包含對外部作用域而非全局作用域的引用。之前都是通過參數將外部的值傳給函數,閉包提供的思路是將參數包起來。
1、什么是閉包?
閉包,即函數定義和函數表達式位于另一個函數的函數體內(嵌套函數)。而且,這些內部函數可以訪問它們所在的外部函數中聲明的所有局部變量、參數。當其中一個這樣的內部函數在包含它們的外部函數之外被調用時,就會形成閉包。
也就是說,內部函數會在外部函數返回后被執(zhí)行。而當這個內部函數執(zhí)行時,它仍然必需訪問其外部函數的局部變量、參數以及其他內部函數。這些局部變量、參數和函數聲明(最初時)的值是外部函數返回時的值,但也會受到內部函數的影響。
def func():
n = 10
def func2():
print("func2:",n) # 對外部作用域的引用
return func2
f = func() # 拿到func2內存地址
print(f) # func2內存地址:.func2 at 0x101fb4620>
f() # 執(zhí)行func2: 10
在外部可以執(zhí)行內部的函數,并且可以使用內部函數作用域里的值,這種現(xiàn)象就是閉包。
在函數里面套了一層子函數,在外層函數被執(zhí)行的時候,子函數被返回了,返回的是內存地址,在外面執(zhí)行子函數的時候用引用了外層函數的變量,相當于兩者有一種扯不掉理還亂的關系。
2、閉包的意義和應用
閉包的意義:返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優(yōu)先使用自己外層包裹的作用域。
應用領域:延遲計算(原來我們是傳參,現(xiàn)在是抱起來)、裝飾器
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'))
四、函數嵌套返回值
age = 18
def func1():
age = 73
def func2():
age = 84
print(age)
return 666
val = func1()
print(val)
'''
輸出:666
'''
函數可以當做返回值:
# 函數名可以當作返回值
age = 18
def func1():
age = 73
def func2():...
return func2 # 返回一個函數名# val = func1()
print(val)
'''
輸出:.func2 at 0x101462598>
'''
# 代碼寫完之后作用域已經生成,不管函數名傳到哪里,只要執(zhí)行都回回定義的地方往上找
age = 18
def func1():
age = 73
def func2():
print(age)
return func2 # 返回一個函數名不帶括號
val = func1()
val()
'''
輸出結果:73
'''
總結
以上是生活随笔為你收集整理的python函数作用域与闭包_python函数名称空间与作用域、闭包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 解码webp动画,and
- 下一篇: td之间的间距怎么改_论文的一级标题、二