1. 程式人生 > >python學習彙總40:名稱空間和作用域及local,global,locals(),globals()區別 2018/11/16(推薦)tcy

python學習彙總40:名稱空間和作用域及local,global,locals(),globals()區別 2018/11/16(推薦)tcy

python名稱空間和作用域及local,global,locals(),globals()區別 2018/11/16  
目錄:
1.名稱空間及作用域的基本概念

1.1.模組級變數運用

2.變數的作用域
3.local,global,locals(),globals()區別
loccals檢視區域性變數
globals檢視修改刪除全域性變數
4.典型錯誤處理   
1.1.名稱空間分類:

全域性名稱空間:記錄模組變數,包括函式、類、匯入模組、模組級變數和常量
區域性名稱空間:函式,類,推導式名字空間叫做區域性名字空間,記錄引數和區域性變數
內建名稱空間:任何模組均可訪問它,存放著內建函式異常
1.2.三種名稱空間之間的載入與取值順序:

載入順序:
內建名稱空間(程式執行前載入)->全域性名稱空間(程式執行中:從上到下載入)->區域性名稱空間(程式執行中:呼叫時才載入)

取值 ,查詢變數順序:
區域性名稱空間->全域性名稱空間->內建名稱空間

區域性名字空間local 本地-  特指當前函式或類方法。
區域性名字空間 Eclosing封閉-  函式體內定義函式
全域性名字空間global全域性 -  特指當前模組。
內建名字空間 built-in內建-  對每個模組都是全域性的。

注意:
import module:模組自身被導,保持自已名字空間;module.function在模組的名稱空間中運用
from module import: 將module.function函式屬性匯入當前名字空間;可以直接使用 
1.3.python程式碼執行函式機理

python直譯器開始執行之後,在記憶體中開闢一個空間,當遇到一個變數時把變數名和值
之間對應關係記錄下來。當遇到函式定義時直譯器只是象徵性將函式名讀入記憶體,表示知
道這個函式存在,至於函式內部的變數和邏輯直譯器根本不關心

程式碼在執行伊始,建立的儲存“變數名與值的關係”的空間叫做全域性名稱空間

等執行到函式呼叫的時候,python直譯器會再開闢一塊記憶體來儲存這個函式裡的內容,
這個時候,才關注函式裡面有哪些變數,而函式中的變數會儲存在新開闢出來的記憶體中。

函式中變數只能在函式內部使用,隨著函式執行完畢這塊記憶體中所有內容被清空
在函式的執行中開闢的臨時的空間叫做區域性名稱空間

內建名稱空間存放python直譯器提供名字input print str list tuple.等.可直接使用。 
2.變數的作用域

概念:
global變數:為全域性作用域;
nonlocal變數:為封閉作用域,系統每次執行函式時會建立新的區域性名稱空間
globals()  :以字典型別返回當前位置的全部全域性變數。
locals()  :以字典型別返回當前位置的全部區域性變數
用途:
用於定義,檢視,修改變數
注意:
1)golbal用於定義全域性變數
2)nonlocal用於函式內定義區域性變數
3)globals,locals函式用名字空間來記錄變數軌跡;名字空間是一個字典 {變數名:變數值}
4)名字空間在執行時直接可以訪問,可在名稱空間中更改變數
(1)區域性名字空間可通過內建locals函式訪問; locals是隻讀 不可修改;locals()返回的拷貝;修改不影響區域性名字空間中變數值
(2)全域性(模組級別)名字空間可通過內建globals函式來訪問;globals可以修改,返回全域性名字空間;對他修改影響全域性變數

5).跨模組共享全域性變數
在單個程式中跨模組共享資訊的規範方式是建立一個特殊模組(通常稱為config或cfg)。
只需在應用程式的所有模組中匯入配置模組;  該模組將成為全域性名稱。由於每個模組只有
一個例項,因此對模組物件所做的任何更改都會反映到處。例如: 

config.py:
x = 0 # Default value of the 'x' configuration setting
mod.py:
import config
config.x = 1
main.py:
import config
import mod
print(config.x)

3.例項 :

例項1-locals()檢視區域性變數
def add_tcy(a,b):
z=a+b
s=locals()
locals()['z'] = -100 # 修改區域性名字空間拷貝變數無影響
return s['z'],z,s

f=add_tcy(3,4) # (-100, 7, {'a': 3, 'b': 4, 'z': -100, 's': {...}})#z並未改變,改變的locals()拷貝的副本 
例項2-globals()檢視修改刪除全域性變數
import os

'name' in globals() #False
globals()['name']=os.getcwd()#'C:\\python37\\Scripts'
'name' in globals() #True
del globals()['name']
'name' in globals() # False 
例項3-globals()在名稱空間中修改全域性變數

x,y=10,20
z=x+y
print(z)#30
globals()['x']=-100 # globals()修改變數x的值為-100
z=x+y
print(z)#80

4.例項:測試全域性變數和區域性變數 

顯示函式定義: 
lst=[0,0]
def view_variable(locals,globals,lst=lst):
'''僅顯示變數,去除其他顯示'''

   def ChooseVariable(data):
     d={}
     for key,value in data.items():
         if ('__' not in key) and (not isinstance(value,dict)) and('lst' not in key):
            if 'function' in str(value):value='fun'
            d[key]=value
            lst[1]=lst[1]+1
            lst[0]=(lst[0]+1) if (lst[1]%2)==0 else lst[0]
     return d

     print('{}.1.locals={}'.format(lst[0],ChooseVariable(locals)))
     print('{}.2.globals={}'.format(lst[0],ChooseVariable(globals))) 
例項1:
g_x0=1 #全域性作用域

l=locals()
g=globals()
view_variable(l,g)
# 1.locals={'view_variable': 'fun', 'g_x0': 1}
# 2.globals={'view_variable': 'fun', 'g_x0': 1} 
例項2:測試全域性變數和區域性變數---閉包變數測試
g1=-1000
def test_func():
   V0=10 #作用域為test_func函式
   l = locals()
   g = globals()
   view_variable(l, g)

      # 0.1.locals={'V0': 10}
      # 0.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun'}

   def local_func():
      V0 = 20 #作用域為本函式
      l = locals()
      g = globals()
      view_variable(l, g)
      # 1.1.locals={'V0': 20}
      # 1.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun'}

   def nonlocal_func():
      nonlocal V0 #作用域為test_func函式內部
      V0=15
      l = locals()
      g = globals()
      view_variable(l, g)
      # 2.1.locals={'V0': 15}
      # 2.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun'}

   def global_func():
      global V0 #新建global全域性變數
      V0=-1
      l = locals()
      g = globals()
      view_variable(l, g)
      # 3.1.locals={}
      # 3.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun', 'V0': -1}

   local_func()
   print("V0=:", V0) # V0=10
   nonlocal_func()
   print("V0=:", V0) #V0=15
   global_func()
   print("V0=", V0) #同名內部優先V0=15
   l = locals()
   g = globals()
   view_variable(l, g)
   # 4.1.locals={'V0': 15, 'local_func': 'fun', 'nonlocal_func': 'fun', 'global_func': 'fun'}
   # 4.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun', 'V0': -1}

測試呼叫
test_func()
print(V0) #V0=-1
l=locals()
g=globals()
view_variable(l,g)
# 5.1.locals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun', 'V0': -1}
# 5.2.globals={'view_variable': 'fun', 'g1': -1000, 'test_func': 'fun', 'V0': -1}
5.錯誤處理:
例項1
def myFunction(param1=123,param2="Python"):
   # global myVar
   for key,val in locals().items():
       print( "key==> (%s : %s)" % (key,str(val)))
   myVar = myVar + 1

myVar = 27
myFunction(12,'Tom')
#預設global myVar程式報錯
#輸出:
# key==> (param1 : 12)
# key==> (param2 : Tom)
#報錯原因:區域性賦值需要注意

Python有如下假設,如果在函式體內的任何地方對變數賦值,則Python將名稱新增到區域性名稱空間。
語句myVar = myVar + 1對名稱myVar進行賦值,Python假設無論在何處發生賦值,myVar都是函式myFunction區域性名稱空間的一部分。
當Python嘗試把1新增到myVar中時,該名稱在區域性名稱空間中,但它沒有關聯值,因此報錯。
    
問題在於Python何時決定myVar出現在區域性空間中,這發生在程式碼執行之前,即,在Python執行到函式定義之前。由於建立區域性名稱空間時
(程式碼實際執行之前)。Python會檢查程式碼並填充區域性名稱空間。在Python執行那行程式碼前,就發現了對myVar的賦值,並把它新增到區域性
名稱空間中。當函式執行時,Python直譯器認為myVar在區域性名稱空間中但沒有值,所以會產生錯誤。
    
解決辦法:
如果在函式體內,使用global語句將變數宣告為全域性變數,那麼Python不會為該變數在名稱空間中建立區域性名稱。 
例項2:典型內部變數運用錯誤

def a(x):
     print(x)
     def b():
         print(x) #報錯,函式內賦值操作對外層變數遮蔽,無論賦值引數在本函式內部位置何處
         x = 20
         print(x)
     return b

f=a(10)()
print(f)

解決辦法 :

def a(x):
     print(x)
     def b():
         nonlocal x  # python3 的 nonlocal 語句可以內部函式直接使用外部函式
         print(x) #報錯,函式內賦值操作對外層變數遮蔽,無論賦值引數在本函式內部位置何處
         x = 20
         print(x)
     return b

f=a(10)()
print(f)

# 10
# 10
# 20
# None