Enclosing->Global->Built-in順序:a=1deffunc1():...print(a)...a=111...print(a)...func1()Traceback(mostrecentcalllast):File"",line1,inFile"",line2,infunc1UnboundLocalError:localvariable'a'referencedbeforeass" />

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

python 函數 變量和閉包

系統 1775 0

首先我們認定,python中定義域查找遵循local->Enclosing->Global->Built-in順序:

a=1
def func1():
... print(a)
... a=111
... print(a)
...
func1()
Traceback (most recent call last):
File " ", line 1, in
File " ", line 2, in func1
UnboundLocalError: local variable 'a' referenced before assignment

而:

a=1
def fun():
... print(a)
... b=111
... print(b)
...
fun()
1
111
print(b)
Traceback (most recent call last):
File " ", line 1, in
NameError: name 'b' is not defined

我們可以得出結論(打臉):內置函數先在內置函數定義域內(前后)尋找變量;找不到之后再從全局變量中引進,且局部變量無法全局。
如果global:

a=1
def func1():
... global a
... print(a)
... a=111
... print(a)
...
func1()
1
111
a
111

但是不多久后我發現一個問題,代碼如下:

a=10
def test():
... a = a + 1
... print(a)
...
test()
Traceback (most recent call last):
File " ", line 1, in
File " ", line 2, in test
UnboundLocalError: local variable 'a' referenced before assignment
test(a)
Traceback (most recent call last):
File " ", line 1, in
TypeError: test() takes 0 positional arguments but 1 was given
所以這個問題其實可以被拆分為兩個問題,一個是arguments的問題,還有一個是variable的問題。
當定義了一個argument的時候只要在括號里把global中的variable代入就是可以運行的,前提就是可一定要定義?。。?!

a=1
def func1(a):
... print(a)
... a=111
... print(a)
...
func1(a)
1
111

也就是說問題根本不在global,而是我有沒有把a帶進去...(哭泣)
結論就是一切都是我自作多情想多了,自己的bug

a=10
def test(a):
... print(a)
... a=a+1
... print(a)
...
test(a)
10
11

所以回到第一個例子,所謂的“local variable referred before assignment”只是因為我沒有把變量在定義的時候放進去。

這是第一件事

第二件:只有模塊,類以及函數才會引入新的定義域,其他代碼塊如(if/else,while)是不會的:

a=0
while a < 4:
... print(a)
... a += 1
...
0
1
2
3
a
4

三: 嵌套和閉包

def out():
... a=7
... def inner():
... nonlocal a
... print(a)
... a=9
... print(a)
... inner()
... print(a)
...
out()
7
9
9

嵌套和nonlocal都超好理解
讓我斯巴達的是如下:

def fun2(a):
... print(a)
... def fun3(b):
... print(a,b)
... return fun3 #返回fun3函數結果
...
fun2(1)
1
.fun3 at 0x000001E2857C24C8>
f=fun2(1)
1
f
.fun3 at 0x000001E2857A4828>
f(4)
1 4

嗯這就是傳說中的閉包,閉包使得函數內部的變量可以一直被保存并且被外部使用(像個自由的包裹一直裹著里面的變量)
為了更直觀一點:

def out():
... def inner():
... a=5
... return a
... inner()
... return inner
...
f=out()
f
.inner at 0x000001E2857A4678>
f()
5

可見調用的這個定義函數,返回的仍舊是一個函數,而不是一個值。out()不是一個函數運行結果而是一個由返回的inner函數和變量a構成的函數(因為閉包的本質就是一種函數,由局部變量和內部函數構成)。
具體一點說來,在第一個例子中,運行fun2(1)將同時得到print出來的一個a,和一個以fun3為函數,被保留的a和未被賦值的b為變量的函數。【當定義符合閉包條件時,自由變量(此處的f)變成一個閉包類,有函數的效果】。
至于為什么它的地址在變化,我覺得是因為它每次調用都返回了一個新函數(分開儲存)。

233333我又看到了一個神奇東西

def count():
... fs=[]
... for i in range(1,4):
... def f():
... return i*i
... fs.append(f)
... return fs
...
f1,f2,f3=count()
f1
.f at 0x000001E2857A4438>
f1()
9
f2()
9
f3()
9

此處函數為閉包的原因在于append的那個f,如果我做一個改動

def count():
... fs=[]
... for i in range(1,4):
... def f():
... return i*i
... fs.append(f())
... return fs
...
count()
[1, 4, 9]

它就不是閉包了,count可以正常輸出結果。
而在這里,返回的函數是i*i,但是由于返回時i=3,f1,f2,f3都變成了9。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 巨鹿县| 闸北区| 清河县| 玉树县| 遂昌县| 商河县| 吉首市| 济南市| 三江| 松阳县| 中超| 阳江市| 贵港市| 建昌县| 河北区| 修水县| 琼结县| 临泉县| 石狮市| 鹤庆县| 翼城县| 孝感市| 遵义市| 新源县| 满城县| 桃园县| 行唐县| 蚌埠市| 阿尔山市| 舟山市| 嘉善县| 兴宁市| 丰都县| 留坝县| 宜良县| 旬邑县| 井研县| 桓台县| 咸阳市| 河曲县| 耒阳市|