2016-04-25 48 views
2

似乎如果我通過幾個文件中的import語句導入同一個Python文件並在其中更改某個文件範圍變量,那麼引用更改對其他模塊將不可見而容器的變化將會。從幾個Python文件中更改相同的文件範圍變量

例如,

第一示例

first.py

import reader 
import helper 


reader.change_buf('modified') 
helper.foo() 

second.py

import reader 


def foo(): 
    print(reader.BUF) 

reader.py

buf = 'original' 


def change_buf(buf): 
    buf = buf 

輸出

> python first.py 
original 

第二示例

first.py

import reader 
import helper 


reader.change_first_element('1') 
helper.foo() 

second.py

import reader 


def foo(): 
    print(reader.BUF) 

reader.py

buf = ['0', '1', '2'] 


def change_first_element(new_elem): 
    buf[0] = new_elem 

輸出

> python first.py 
['1', '1', '2'] 

爲什麼?

回答

0

tl; dr因爲你對不同的行爲做了不同的事情。

  1. 在你的第一個例子,在新建功能change_buf一個局部變量buf;在第二個例子中,沒有這樣的變量可以在本地訪問,所以python會向下搜索堆棧,尋找適合您請求的變量,並在模塊級範圍中找到一個變量。
  2. 您的第一個示例使用賦值語句,您的第二個語句是花式setitem表示法。這兩種行爲是不同的。

解釋(1)中,This question is similar的行爲。如果你想使用賦值語句明確訪問一個全局變量,使用global or nonlocal keywordas is done here

從文檔:

這將是不可能分配到一個全局變量沒有全球性的,但免費變量可以指全局變量而不被聲明爲全局變量。

請注意,您的第二個示例不是一個賦值語句;它是一個調用__setitem__的變量buf的方法,這恰好是類型列表。它可能會更有意義看起來像這樣

foo = [3] 
def set_foo(): 
    foo.__setitem__(0,3) 

現在你看到foo被參考的「自由變量」,並能來引用該名稱在全球範圍內的元素。如果對於屬於哪個範圍foo有任何不明確性,python將無法處理您的案例。


Python的約作用域可以稍微複雜的規則,but are unambiguous

0

很簡單,因爲在第一個例子中,你都躲在全局變量buf後的本地一個(函數參數buf),而在第二個例子中,功能參數(new_elem)不會發生碰撞。但那不是全部。在第一個例子中,你定義了變量buf在一個函數中,所以它仍然是本地的默認 - 在第二個例子中,你自己使用它自從你設置了buf[0]。您必須聲明它global

你應該寫reader.py這樣:

buf = 'original' 

def change_buf(new_val): 
    global buf 
    buf = new_val