2015-06-27 60 views
-3

我跑到下面的代碼爲什麼這種不同的行爲?我對嗎?

global_var1 = 1 
global_var2 = 2 

def func(): 
    print(global_var1) 
    print(global_var2) 
    global_var2 = 3 

func() 

它扔錯誤

Traceback (most recent call last): 
    File "/home/harish/PycharmProjects/try/scope.py", line 10, in <module> 
    func() 
    File "/home/harish/PycharmProjects/try/scope.py", line 7, in func 
    print(global_var2) 
UnboundLocalError: local variable 'global_var2' referenced before assignment 

但下面的代碼工作

__author__ = 'harish' 
global_var1 = 1 
global_var2 = 2 

def func(): 
    print(global_var1) 
    print(global_var2) 
func() 

我的期望是funcion func調用時。它會尋找global_var1,它不是本地的,所以它看起來在全球範圍內並打印它。 然後類似地,它會尋找global_var1,它不是本地,所以它看起來在全球並打印它。那麼它會在localscope中創建一個變量global_var2並分配3。

可能沒有像上面那樣完成,因爲在相同的功能範圍內,同一個變量global_var2有不同的含義。直到第2行,它指的是全球性的,然後是當地的..我的猜測是否正確?

回答

1

global聲明應放在功能:

def func(): 
    global global_var2 
    print(global_var1) 
    print(global_var2) 
    global_var2 = 3 

他們告訴蟒蛇該函數內部名稱global_var2是指全球範圍內,而不是本地的。將global聲明放在頂層是無用

Python不允許在同一個作用域內引用兩個不同的作用域,所以賦值global_var2 = 3強制該變量是本地的。因此,如果您嘗試在提出錯誤之前將其打印出來。但是如果你對python說這個名稱實際上是全局名稱,那麼python知道他應該從該範圍中取值,並將其賦值給全局範圍。

特別是:

a = 1 

def f(): 
    print(a) 
    a = 2 

在這裏,在print(a)aaa = 2總是指代相同的變量。在上面的代碼裏面f本地因爲沒有提供聲明並且有一個賦值。所以print(a)試圖訪問一個沒有值的局部變量。

如果添加global

a = 1 
def f(): 
    global a 
    print(a) 
    a = 2 

現在所有的a S IN f指全球a,所以print(a)打印1,因爲它是全局變量的值並執行f後的值將成爲2

+0

我知道函數def會在被調用之前執行(例如,這有助於在默認參數設置期間)..將掃描整個函數體嗎?它是如何工作的 ? python如何知道這個局部變量global_var2直到它被執行? –

+0

@HarishKayarohanam我不明白你在說什麼。爲了創建一個函數對象,python必須編譯它的所有主體。編譯所有主體時,它會查找所有的分配,並發現所有局部變量的名稱。這個賦值是在第一次使用之後的事實並不意味着python並不知道函數中的某個地方有*賦值。簡單的事實是,這種賦值迫使變量在函數內的所有用途中都是局部的。期。 – Bakuriu

+1

@HarishKayarohanam以這種方式思考:每個局部變量都在函數的開始處隱式地聲明。所以就像'f'是:'def f():local a;打印的(a); a = 2'。簡單地說'本地a'是隱含的,所以你不寫它。如果你把一個'global a'或'nonlocal''聲明放在它上面。 – Bakuriu

1

Python在編譯時查找函數中的局部變量。每個功能只有一個範圍。所以global_var2是本地的,因爲它在函數的最後一行被定義爲局部變量。

+0

我問@bakaru。但這個疑問也可以問你,,,,,我知道函數def將被執行之前甚至被稱爲(例如,這有助於在默認參數設置)..將整個函數體進行掃描?它是如何工作的 ? python如何知道這個局部變量global_var2直到它被執行? –

+1

@HarishKayarohanam:你知道,編譯器是什麼?代碼在執行之前被解析和分析。這樣,執行器可以爲堆棧中的局部變量保留所需的空間。 – Daniel