2013-10-10 80 views
0

另一個給我提出問題的簡單問題。Python中的名稱空間和模塊

假設我有以下幾點:

#!/usr/bin/python 
ref = 30 
def f(x): 
    print x + ref 
f(50) 

一方面這是方便我的目的,迄今爲止的是,(我想)裁判作爲一個全局變量處理由函數˚F,等等不需要被指定爲f的參數。

不過,我得到的問題時,我想存儲˚F在一個單獨的模塊,說myfunctions

#!/usr/bin/python 
import myfunctions 
ref = 30 
myfunctions.f(50) 

其中myfunctions包含如上˚F定義。當試圖運行這個時,我得到NameError,「全局名稱ref'沒有被定義。」

我猜測,這是因爲主模塊和「myfunctions」模塊有不同的全局命名空間,但有一個很好的辦法解決這 - 而不一定必須包括裁判˚F的說法?

+4

但是,爲什麼你不顯式傳遞變量作爲函數的參數?顯式通常比隱式更好(並且更清晰)... –

+0

問題不在於'myfunctions' *模塊*具有不同的全局名稱空間。問題是*函數*'f'具有不同的全局名稱空間,它是'myfunctions'模塊的'__dict__'。檢查「f.func_globals」屬性與「myfunctions .__ dict__」相同。這是非常明智的,否則每次使用函數時都必須知道它們所需的所有全局變量。這可能意味着你有*閱讀源代碼,或者所有功能的文檔都會很長。 – Bakuriu

+0

謝謝大家 - 在我的情況下,問題是f實際上是一個相當長的函數,使用大約20個來自主命名空間的變量 - 只要在主模塊中定義了f,我就可以避免(繁瑣的)列表任務所有這些都是論據。這是否意味着如果在單獨的模塊中定義了f,則無法做到這一點? – user2383521

回答

2

正如你發現全局變量不這樣工作 - 他們也不應該。以下是你可以做的一些事情,但不應該。

myfunctions.py

ref = 30 
def f(x): 
    print x + ref 

our_caller.py

import myfunctions 
myfunctions.f(10) # prints 40 
myfunctions.ref = 50 
myfunctions.f(10) # prints 60 

但是後來怎麼樣some_other_caller.py?

import myfunctions 
myfunctions.f(20) # prints 50? prints 70? 

這取決於當你與myfunctions模塊中的全局變量混亂周圍。

另外,作爲一個思想實驗,想象你上面發佈的代碼的確如你所期望的那樣工作(它會在某些語言中)。在some_other_caller導入導入myfunctions的our_caller的情況下會發生什麼情況。那麼使用哪個ref?它可能更復雜一些,some_other_caller可以在our_caller中調用函數,然後調用myfunctions.f - 所以我們使用our_caller中的ref?那麼,如果some_other_caller直接調用myfunctions,行爲可能會有所不同?

這不是世界上任何人想住在

做的是更好的方式更像是:

myfunctions.py

def f(x, ref=30): 
    print x + ref 

our_caller.py

import myfunctions 
myfunctions.f(10) # prints 40 
myfunctions.f(10, ref=50) # prints 60 

然後人們可以看到發生了什麼 - 沒有奇怪的狀態改變。全球狀態真的是最好的避免。你會一次又一次地聽到。在你自己的危險(以及後來必須支持你的代碼的任何可憐的靈魂)中忽略這個建議。

編輯:除上述有關您的用例的註釋之外,看到類似以下的模式並不罕見。

REF = 30 
ref_count = 0 

def f(x, ref=REF, other_thing=None): 
    if not other_thing: 
     other_thing = ref_count 
    print x + ref + other_thing 

def add_ref(current_count=None): 
    global ref_count 
    if current_count is not None: 
     ref_count = current_count 
    ref_count += 1 

您可以保留全局變量(REF更像是一個全局常量)。當你從外部調用f時,你可以選擇爲它們提供值或允許它們成爲默認值。此外,您可以調用add_ref,爲其提供一個新值以用於模塊中的全局副本。

同樣,同樣的規則適用 - 您已將全局狀態添加到您的模塊,這可能受外部模塊影響。你需要非常小心誰在改變它,一個更好的架構會首先嚐試避免這種情況。

相關問題