pythonfor作用域
1. python中函數變數作用域和類變數作用域怎麼搞都錯,煩躁中
python中,變數的作用域要弄清楚。只有mole、class、def、lambda才會引入作用域,其他的代碼塊是不會引入作用域的。
1
圖一中,你在函數中聲明了d為全局變數,但這樣是無效的,程序運行結果,已經說明這一點。
global這個關鍵字,是用來「在函數中修改全局變數值」的聲明,而不是「在局部函數中定義一個全局變數」的聲明。這里要注意一下。
你可以再局部函數外面聲明變數d,再加上你原先的函數,就可以修改、訪問這個變數了。
2
在類中函數的變數,作用域只在函數中。圖二中,jian這個變數分別在yu(),yu1()兩個函數中,是處於不同的定義域中的,是不能相互訪問的。
所以,在各自函數中,只有先定義了jian變數,才能再使用。
如果想在yu1()中訪問yu()中的jian變數,就需要將jian變數變成全局變數,即在class中定義一個全局變數jian,這樣yu1(),yu()函數都可以訪問了
2. python跨模塊作用域
python中的作用域分4種情況:
L:local,局部作用域,即函數中定義的變數;
E:enclosing,嵌套的父級函數的局部作用域,即包含此函數的上級函數的局部作用域,但不是全局的;
G:globa,全局變數,就是模塊級別定義的變數;
B:built-in,系統固定模塊裡面的變數,比如int, bytearray等。 搜索變數的優先順序順序依次是:作用域局部>外層作用域>當前模塊中的全局>python內置作用域,也就是LEGB。
1
2
3
4
5
6
7
8
9
10
11
12
13
x = int(2.9) # int built-in
g_count = 0 # global
def outer():
o_count = 1 # enclosing
def inner():
i_count = 2 # local
print(o_count)
# print(i_count) 找不到
inner()
outer()
# print(o_count) #找不到
當然,local和enclosing是相對的,enclosing變數相對上層來說也是local。
5.2 作用域產生
在Python中,只有模塊(mole),類(class)以及函數(def、lambda)才會引入新的作用域,其它的代碼塊(如if、try、for等)是不會引入新的作用域的,如下代碼:
1
2
3
if 2>1:
x = 1
print(x) # 1
這個是沒有問題的,if並沒有引入一個新的作用域,x仍處在當前作用域中,後面代碼可以使用。
1
2
3
def test():
x = 2
print(x) # NameError: name 'x2' is not defined
def、class、lambda是可以引入新作用域的。
5.3 變數的修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#################
x=6
def f2():
print(x)
x=5
f2()
# 錯誤的原因在於print(x)時,解釋器會在局部作用域找,會找到x=5(函數已經載入到內存),但x使用在聲明前了,所以報錯:
# local variable 'x' referenced before assignment.如何證明找到了x=5呢?簡單:注釋掉x=5,x=6
# 報錯為:name 'x' is not defined
#同理
x=6
def f2():
x+=1 #local variable 'x' referenced before assignment.
f2()
5.4 global關鍵字
當內部局冊轎作用域想修改外部作用域姿粗的變數時,就要用到global和nonlocal關鍵字了,當修改的變數是在全局作用域(global作用域)上的,就要使用global先聲明一下,代碼如下:
1
2
3
4
5
6
7
8
9
count = 10
def outer():
global count
print(count)
count = 100
print(count)
outer()
#10
#100
5.5 nonlocal關鍵字
global關鍵字聲明的變數必須在全局作用域上,不能嵌套作用域上,當要修改嵌套作用域(enclosing作用域,外層非全局作用域)中的變數怎麼辦呢,這時就需要nonlocal關鍵字了
1
2
3
4
5
6
7
8
9
10
11
def outer():
count = 10
def inner():
nonlocal count
count = 20
print(count)
inner()
print(count)
outer()
#20
#20
5.6 小結
(1)變數查找順序:LEGB,作用域局部>外層作用域>當前模塊中的全局>python內置作用域;
(2)只有模塊、類、及函數才能引入新作用域;
(3)對於一個變數,內部作用域先聲明就會覆蓋外部變數,不聲明直接使用,就會使用外部作用域的變數;
(4)內部作用域要修改外部作用域變數的值時,全局變數要使用global關鍵字,嵌套作用域變數要使用nonlocal關鍵字。桐肆nonlocal是python3新增的關鍵字,有了這個 關鍵字,就能完美的實現閉包了。
3. python 函數作用域問題,
類在定義的帆慶時陪轎森候是蘆畝有作用域的,這個作用域內的變數只能在 class 塊內訪問,而不能在類的方法(函數)中訪問。
4. Python語言中作用域怎麼理解
命名空間 是從命名到對象的映射。當前命名空間主要是通過 Python 字典實現的,不過通常不關心具體的實現方式(除非出於性能考慮),以後也有可能會改變其實現方式。以下有一些命名空間的例子:內置命名(像 abs() 這樣的函數,以及內置異常名)集,模塊中的全局命名,函數調用中的局部命名。某種意義上講對象的屬性集也是一個命名空間。關於命名空間需要了解的一件很重要的事就是不同命名空間中的命名沒有任何聯系,例如兩個不同的模塊可能都會定義一個名為 maximize 的函數而不會發生混淆-用戶必須以模塊名為前綴來引用它們。
順便提一句,我稱 Python 中任何一個「.」之後的命名為 屬性 --例如,表達式 z.real 中的 real 是對象 z 的一個屬性。嚴格來講,從模塊中引用命名是引用屬性:表達式 modname.funcname 中,modname 是一個模塊對象,funcname 是它的一個屬性。因此,模塊的屬性和模塊中的全局命名有直接的映射關系:它們共享同一命名空間![1]
屬性可以是只讀過或寫的。後一種情況下,可以對屬性賦值。你可以這樣做: modname.the_answer = 42 。可寫的屬性也可以用 del 語句刪除。例如: del modname.the_answer 會從 modname 對象中刪除 the_answer 屬性。
不同的命名空間在不同的時刻創建,有不同的生存期。包含內置命名的命名空間在 Python 解釋器啟動時創建,會一直保留,不被刪除。模塊的全局命名空間在模塊定義被讀入時創建,通常,模塊命名空間也會一直保存到解釋器退出。由解釋器在最高層調用執行的語句,不管它是從腳本文件中讀入還是來自互動式輸入,都是 __main__ 模塊的一部分,所以它們也擁有自己的命名空間(內置命名也同樣被包含在一個模塊中,它被稱作 builtins )。
當調用函數時,就會為它創建一個局部命名空間,並且在函數返回或拋出一個並沒有在函數內部處理的異常時被刪除。(實際上,用遺忘來形容到底發生了什麼更為貼切。)當然,每個遞歸調用都有自己的局部命名空間。
作用域 就是一個 Python 程序可以直接訪問命名空間的正文區域。這里的直接訪問意思是一個對名稱的錯誤引用會嘗試在命名空間內查找。盡管作用域是靜態定義,在使用時他們都是動態的。每次執行時,至少有三個命名空間可以直接訪問的作用域嵌套在一起:
5. python裡面變數作用域是什麼
變數作用域:python可以直接查找名稱到對象的映射(命名空間)的部分。
python有built–in、global、enclosing、local這四種作用域
built–in:內建作用域,包含了內建的變數和關鍵字。
global:全局作用域,定義在所有函數外,當前模塊(.py源文件)的全局變數。
enclosing:閉包函數外的函數(非局部也非全局),比如有一個函數a,a里有另一個函數b,對於b里的變數來說,a中的作用域就是enclosing。
local:局部作用域,腳本最內層,比如函數里。
6. Python其實很簡單 第十二章 函數與變數的作用域
在前面已經多次提到函數這個概念,此慎孝之所以沒有解釋什麼是函數,是因為程序中的函數和數學中的函數差不多,如input()、range()等都是函數,這些都是Python的標准函數,直接使用就可以了。根據需要,用戶也可以自定義函數。
12.1 函數
函數的結構:
def 函數名(參數):
函數體
return 返回值
例如:數學中的函數f(x)=2x+5在Python中可以定義如下:
def f(x):
y=2*x+5
return(y)
如果x取值為3,可以使用如下語句調用函數:
f(3)
下面給出完整的程序代碼:
def f(x):
y=2*x+5
return(y)
res=f(3)
print(res)
運行結果:11
如上例中的x是函數f(x)的參數,有時也被稱為形式參數(簡稱形參),在函數被調用時,x被具森稿體的值3替換y就是函數的返回值,這個值3也被稱為實際參數(簡稱實參)。
上例中的y是函數f(x)的返回值。並不是所有的函數都有參數和返回值。如下面的函數:
def func():
print('此為無參數傳遞、無返回值的函數')
func()
輸出結果:此為無參數傳遞、無返回值的函數
可以看出,該函數func()無參數,故調用時不用賦給參數值。
函數也可以有多個參數,如f(x,y)=x²+y²,可用Python語言定義如下:
def f(x,y):
z=x**2+y**2
return z
print(f(2,3)) #調用函數f(x,y)
輸出結果:13
也可以通過直接給參數列表中的參數賦值的方法,為參數添加默認值,如果用戶賦予參數值,則按照用戶賦值執行,否則使用默認值。例如:
def f(x,y=3):
z=x**2+y**2
return z
若調用時參數列表為(2,1),即x賦值為2,y賦值為1:
print(f(2,1))
輸出結果為:5
若調用時參數列表為(2),即x賦值為2,y賦值省缺,則y使用默認值:
print(f(2))
輸出結果為:13
回調函孝凱數,又稱函數回調,是將函數作為另一函數的參數。
例如:
def func(fun,m,n):
fun(m,n)
def f_add(m,n):
print('m+n=',m+n)
def f_mult(m,n):
print('m*n=',m*n)
func(f_add,2,3)
func(f_mult,2,3)
輸出結果:
m+n= 5
m*n= 6
在f_add(m,n)和f_mult(m,n)被定義前,func(fun,m,n)中的fun(m,n)就已經調用了這兩個函數,即「先調用後定義」,這也是回調函數的特點。
如果無法預知參數的個數,可以在參數前面加上*號,這種參數實際上對應元組類型。譬如,參會的人數事先不能確定,只能根據與會人員名單輸入:
def func(*names):
print('今天與會人員有:')
for name in names:
print(name)
func('張小兵','陳曉梅','李大海','王長江')
運行後,輸出結果為:
今天與會人員有:
張小兵
陳曉梅
李大海
王長江
參數為字典類型,需要在參數前面加上**號。
def func(**kwargs):
for i in kwargs:
print(i,kwargs[i])
func(a='a1',b='b1',c='c1')
輸出結果為:
a a1
b b1
c c1
一個有趣的實例:
def func(x,y,z,*args,**kwargs):
print(x,y,z)
print(args)
print(kwargs)
func('a','b','c','Python','is easy',py='python',j='java',ph='php')
輸出結果:
a b c # 前三個實參賦給前三個形參
('Python', 'is easy') # *args接收元組數據
{'py': 'python', 'j': 'java', 'ph': 'php'} # **kwargs接收字典數據
12.2 變數的作用域
變數的作用域即變數的有效范圍,可分為全局變數和局部變數。
局部變數
在函數中定義的變數就是局部變數,局部變數的作用域僅限於函數內部使用。
全局變數
在主程序中定義的變數就是全局變數,但在函數中用關鍵字global修飾的變數也可以當做全局變數來使用。
全局變數的作用域是整個程序,也就是說,全局變數可以在整個程序中可以訪問。
下面通過實例去討論:
程序1:
a=1 # a為全局變數
def a_add():
print('a的初值:',a) # 在函數中讀取a的值
a_add() # 調用函數a_add()
a+=1 # 主程序語句,a增加1
print('a現在的值是:',a) # 主程序語句,讀取a的值
運行結果:
a的初值: 1
a現在的值是: 2
這個結果和我們想像的一樣,全局變數a既可以在主程序中讀取,也可以在子程序(函數)中讀取。
程序2:
a=1
def a_add():
a+=1
print('a的初值:',a)
a_add()
print('a現在的值是:',a)
運行程序1時出現如下錯誤提示:
UnboundLocalError: local variable 'a' referenced before assignment
意思是:局部變數'a'在賦值之前被引用。
從語法上來講,該程序沒有錯誤。首先定義了一個全局變數a並賦值為1,又定義了一個函數a_add(),函數內的語句a+=1就是出錯的根源,雖然我們的初衷是想讓全局變數a的值增加1,但從錯誤提示看,這個語句中的a並不是全局變數,而是局部變數。看來,在函數中讀取全局變數的值是沒有問題的(在程序1中已經得到了驗證),但要在函數中改變全局變數的值是不行的(在程序2的錯誤提示a+=1中的a 是局部變數,而非全局變數)。
怎樣解決這個問題?
程序3:
a=1
def a_add(x):
x+=1
return x
print('a的初值:',a)
a=a_add(a)
print('a現在的值是:',a)
運行結果:
a的初值: 1
a現在的值是: 2
結果的確是正確的,但在函數a_add(x)中沒有調用變數a(沒有出現變數a)。
程序4:
a=1
def a_add(a):
a+=1
return a
print('a的初值:',a)
a=a_add(a)
print('a現在的值是:',a)
運行結果:
a的初值: 1
a現在的值是: 2
對比程序4和程序3不難發現,其實程序4隻是簡單的把函數的參數x變成了a,這個a的實質和程序3中的x還是一樣的。這進一步證實,函數中的a是局部變數,與主程序的全局變數a有著本質的區別。
程序5:
a=1
def a_add():
global a
a+=1
print('a的初值:',a)
a_add()
print('a現在的值是:',a)
運行結果:
a的初值: 1
a現在的值是: 2
程序5和程序2相比較,僅僅是在函數中添加了一個定義「global a」,此時的局部變數a就可以當做全局變數使用,由於它和全局變數a同名,自然也就不用區分a究竟是全局變數還是局部變數了,在主程序和該函數內都可以訪問、修改變數a的值了。
雖然使用global可使變數使用起來非常方便,但也容易引起混淆,故在使用過程中還是謹慎為好。
12.3 函數的遞歸與嵌套
遞歸,就是函數調用它自身。遞歸必須設置停止條件,否則函數將無法終止,形成死循環。
以計算階乘為例:
def func(n):
if n==1:
return 1
else:
return n*func(n-1) #func( )調用func( )
print(func(5))
運行結果為:120
嵌套,指在函數中調用另外的函數。這是程序中常見的一種結構,在此不再贅述。
匿名函數
Python中可以在參數前加上關鍵字lambda定義一個匿名函數,這樣的函數一般都屬於「一次性」的。
例如:
程序1:這是一個常規的函數定義和調用。
def f_add(x,y):
return x+y
print(f_add(2,3))
輸出結果:5
程序2:使用lambda定義匿名函數。
f_add=lambda x,y:x+y
print(f_add(2,3))
輸出結果:5
從上面的代碼可以看出,使用lambda僅僅減少了一行代碼。f_add=lambda x,y:x+y中的f_add不是變數名,而是函數名。程序1和程序2的print( )語句中的參數都是一樣的——調用函數f_add( )。所以,匿名函數並沒有太多的優點。
7. python函數實參不是的作用域問題,高手來解釋下下面的輸出
可以先不看f(3,[3,2,1]),這個就是來迷惑人的,光碧襪看f(2),f(3),Python函數在定義的時候,默認參數L,它指向一個對象[ ],這個對象是和函數同生同死的,每次調用該函數,都會默認指向[ ] ,除非傳遞了第二個參數,則改變了L的指向,但是如果前面修改了這個對象,所以也會在後面體現出來,因為他是一個默認改拍指向的對象。核慧羨所以,定義默認參數要牢記一點:默認參數必須指向不變對象!
8. #抬抬小手學Python# Python 之作用域下的 global 和 nonlocal 關鍵字
該部分內容涉及 Python 變數作用域相關知識,變數作用域指的是變數的有效作用范圍,直接理解就是 Python 中的變數不是任意位置都可以訪問的,有限制條件。
一般情況下變數的作用域變化范圍是 塊級、函數、類、模塊、包等,級別是從小到達。Python 中是沒有塊級作用域的,所以我們在寫代碼的時候,下面的代碼是正確的。
在 Python 中常見的塊級作用域有 if 語句、for 語句、while 語句、with 上下文語句。
上文已經提及了作用域是 Python 程序可以直接訪問一個變數的作用范圍,Python 的作用域一共有 4 種,分別如下:
一個比較經典的案例如下:
在 Python 中變數尋找的順序是從內到外,先局部,然後外部,在全局,在內建,這種規則叫做 LEGB 規則 。
增加以下學習的趣味性,你可殲宏以研究下述代碼中變數是如何變化的。
定義在 函數內部 的變數擁有一個局部作用域,定義在敬激 函數外部 的變數擁有全局作用域。
輸出結果,函數氏稿冊內部是 123 ,函數外部依舊是 0 。
如果希望函數內部(內部作用域)可以修改外部作用域的變數,需要使用 global 關鍵字。
此時輸出的就都是 123 了,還有一點需要注意,在函數內容如果希望修改全局變數的值, global 關鍵字一定要寫在變數操作前。
該代碼會出現語法錯誤:
全局變數還存在一個面試真題,經常出現,請問下述代碼運行結果。
如果要修改嵌套作用域(Enclosing 作用域)中的變數,需要 nonlocal 關鍵字,測試代碼如下:
輸出結果自行測試,注意 nonlocal 關鍵字必須是 Python3.X+版本,Python 2.X 版本會出現語法錯誤:
在多重嵌套中, nonlocal 只會上溯一層,如果上一層沒有,則會繼續上溯,下述代碼你可以分別注釋查看結果。
局部變數和全局變數具體有哪些,可以通過 locals() 和 globals() 兩個內置函數獲取。
本篇博客為大家說明了 Python 的作用域,並且對 global 和 nonlocal 關鍵字進行了學習,希望對你有所幫助。
9. python的關鍵字有哪些,都是什麼意思
我這里匯總Python經常用到的27個關鍵字,希望對正在學Python的你能夠起到幫助
1 and:邏輯與
2 as:為導入的模塊取一個別名,在Python2.6中新增
3 assert:斷言,在Python1.5新增
4 break:用在循環語句,跳轉到語句塊的末尾
5 class:用來定義一個類
6 continue:和break香對應,跳到語句塊的開頭
7 def:用來定義一個函數或方法
8 del:刪除
9 elif:全稱是else if
10 exec:內置函數。執行以string類型存儲的Python代碼
11 finally:用在異常處理語句try-excep-finally中
12 for:著名的for循環,可以用來遍歷一個列表
13 from:字面意思,表示從一個包導入某個模塊
14 global:在函數或其他局部作用域中使用全局變數
15 if:如果
16 import:導入
17 in:在,後面跟一個列表,字典或字元串
18 is:邏輯判斷
19 not:邏輯非
20 or:邏輯或
21 pass:佔位符,用來告訴Python這里不用考慮
22 print:寫得最多的關鍵字,後來在Python3.0中變成了內置函數
23 raise:用來引發一個異常
24 return:函數返回
25 try:異常處理機制
26 while:while循環
27 with:在Python2.6中新增,使用with候不管with中的代碼出現什麼錯誤,都會進行對當前對象進行清理工作,注意該句話後面有一個冒號表示with語句。
以上就是我匯總的部分關鍵字,希望對你有所幫助
10. Python 中作用域與命名空間的問題
i=2這一句是定義了一個局部變數i,並賦值為2;這個時候全局作用域的i會被屏蔽,所以全局變數i是沒有被修改的所以結果是1;
訪問全局變數時可以直接訪問,但是修改全局作用域的時候一定要在賦值之前,進行如下聲明:
deff():
globali
i=2
因為python里賦值語句和聲明變數是一個體的,所以需要global來告訴解釋器i是全局變數,接下來的i=2才能被當作是賦值
------------------追答---------------------
同一個代碼塊(作用域)里, 同一個變數的作用域只能是同一種或者說同一個變數只能來自同一個作用域, 不能是一會是局部變數然後又變成全局變數;
i = i + 1
首先前面的'i='表明了i是一個局部變數(沒有global聲明, 創建局部變數), 然後後面的'i+1'里的i自然也是局部變數(同一個函數下同一個變數,i已經是局部變數了, 不能再當作全局變數去用), 那麼自然會報錯, i在使用前未聲明
i += 1
報錯就更明顯了, 沒有global聲明 那麼再修改變數i的時候, 自然是當作局部變數, 使用前未聲明
變數的查找順序遵循 LEGB 可以自己網路
關於作用域給你再寫個簡單的示例, 你對照著理解一下