2010-03-01 59 views
7

我目前正在用Python開發一些東西,並且我有一個關於變量範圍的問題。關於變量範圍的正確性

這是代碼:

a = None 
anything = False 
if anything: 
    a = 1 
else: 
    a = 2 

print a # prints 2 

如果刪除了第一線(=無)的代碼仍然有效如前。但是在這種情況下,我會在「if」塊中聲明變量,並且關於其他語言(如Java),該變量只會在「if」中可見。

Python中確切的變量範圍工作原理以及在這種情況下編程的好方法是什麼?

謝謝!

+2

在python中沒有「聲明」一個變量的東西! – 2010-03-01 23:06:28

回答

8

作爲一個經驗法則,範圍在三個地方被創建:

  1. 文件範圍 - 另外稱爲模塊範圍
  2. 類範圍 - 內class
  3. 函數作用域的創建 - 裏面def

創建(有一些例外這些。)

分配給名稱將其保留在範圍名稱空間中,標記爲未綁定,直至到達第一個分配。因此,對於心理模型,您正在爲範圍中的名稱分配值。

+1

實際上有四個地方,第四個是全球範圍。但這真的取決於你是否認爲全球範圍本身就是一個範圍。 – jathanism 2010-03-01 23:23:55

+1

據我瞭解全球範圍,它通常是文件/模塊範圍的同義詞。我所瞭解的例外涉及將全局變量字典傳遞給'exec'或'eval'。從內存中,第四個範圍在生成器表達式中找到,不允許迭代器變量轉義。第五個是關閉的非本地塊範圍 - 我從來沒有找到一個簡單的方法來解釋這個範圍。 – 2010-03-01 23:50:57

+0

+1好的答案。 – 2010-03-02 07:17:15

2

我相信Python使用函數作用域作爲局部變量。也就是說,在任何給定的函數中,如果您爲某個局部變量賦值,則該函數將從該函數內的那一刻起可用,直到它返回。因此,由於您的代碼的兩個分支都保證分配給a,所以最初不需要將None分配給a

請注意,如果您還可以訪問在外部函數中聲明的變量 - 換句話說,Python有閉包。

def adder(first): 
    def add(second): 
     return first + second 

    return add 

這定義了一個稱爲加法器的函數。當用參數first調用時,它將返回一個函數,它將接收的任何參數添加到first並返回該值。例如:

add_two = adder(2) 
add_three = adder(3) 
add_two(4) # = 6 
add_three(4) # = 7 

不過,雖然你可以閱讀從外部函數的值,你不能改變它(不像許多其他語言)。例如,設想嘗試實施累加器。你可能會寫代碼,像這樣:

def accumulator(): 
    total = 0 
    def add(number): 
     total += number 
     return total 
    return add 

不幸的是,試圖在一個錯誤信息使用此代碼的結果:

UnboundLocalError: local variable 'total' referenced before assignment 

這是因爲total += number試圖線路改變total的價值,不能用在Python中以這種方式完成。

+0

您可以使用'nonlocal'(Python 3中的new)在'accumulator()'示例中執行所需的操作。 – 2010-03-01 23:33:52

0

Python不需要首先聲明變量,所以你可以在任意點聲明和定義。是的,範圍是功能範圍,所以它在if之外將是可見的。

1

if塊中分配變量沒有問題。

在這種情況下,它被分配到兩個分支上,所以你可以看到它在你打印時肯定會被定義。

如果其中一個分支的沒有分配給a那麼當您嘗試分支

0

我很初學者程序員後打印它NameError異常將會被提高,但我知道,在python私有變量不存在。有關詳細討論,請參閱python文檔中的private variables

有用的信息也可以在同一頁面上的「範圍和名稱空間」部分找到。

個人而言,我寫這樣你幾乎每天張貼的一個,尤其是當條件

if len(sys.argv)==2: 
    f = open(sys.argv[1], 'r') 
else: 
    print ('provide input file') 

我做聲明變量使用他們的結構化類型之前依靠從用戶獲得的輸入,例如代碼,例如我在一個循環中追加它的項目之前聲明一個空列表。

希望它有幫助。