2011-04-15 74 views
0

當我調用一個函數,我希望能夠在功能定義動態的變量名,像這樣......什麼是對的方法動態定義局部變量的最佳方式

def build_ports(portlist): 
    for idx, portname in enumerate(portlist): 
     chassis, slot, port = portname.split('/') 
     vartxt = "p%i" % idx 
     locals()[vartxt] = Port() # Class defining a port object 
     locals()[vartxt].port_method1(chassis, slot, port) 
     if idx > 5: 
      locals()[vartxt].port_method2() # Only call this object method, if idx > 5 

但我們都知道,locals()是隻讀的,不像globals() ...這樣的解釋,當它看到locals()[vartxt] barfs ...

有什麼方法來定義一個方法動態變量不會污染全局命名空間(或更糟的是,在方法中使用全局變量,何時從未在該方法中定義)?

+0

爲什麼不在任何地方使用「端口」? – Stefano 2011-04-15 12:14:56

+0

我簡化了代碼 – 2011-04-15 12:17:53

+0

賦值語句創建一個局部變量。爲什麼要做其他事情?你的「基於索引命名的變量」是字典的用途。你爲什麼不爲這個使用簡單的'dict'? – 2011-04-15 13:12:29

回答

6

使用列表來代替稱爲變量變量的這種瘋狂。

def build_ports(portlist) 
    ports = [] 
    for idx, portname in enumerate(portlist): 
     ports.append(Port()) 
     ports[-1].port_method1() 
     if idx > 5: 
      ports[-1].port_method2() 

而不是使用ports[-1]的,你可能反而廢棄不用的portname迭代變量,並創建一個本地portname = Port(),用它來調用的方法,然後在最後追加到ports。無論如何,portlist

+0

我第二次 - 雖然這個功能的整個邏輯確實逃脫了我。如果你真的想命名變量,你可以使用'dict'而不是列表 – Stefano 2011-04-15 12:15:45

+0

@Stefano,'portlist'是端口名稱的文本列表...例如,'['1/5/9','2/7/13']'...這些用於構建相應的端口對象。我不喜歡管理匿名對象的列表...帶有動態密鑰名稱的字典是一個有趣的選項。 – 2011-04-15 12:19:46

+0

感謝@Mike,我想用完整的非簡化代碼會更有意義,並且@delnan問題也會得到解答!你對他的回答滿意嗎?還是有些不起作用?爲什麼不按照他的建議簡單地使用本地'port'對象呢? – Stefano 2011-04-15 12:24:11

-1

結賬exec

編輯:是的,我的意思是執行。

+2

-1 ** No。**即使它在技術上有效(它不會 - 你需要'exec'來完成任務)......有一個完美的清晰,高性能,地道,明顯的解決方案! – delnan 2011-04-15 12:13:25

+0

@delnan:是的,我的意思是執行。謝謝。 – 2011-04-15 12:19:26

3

不,這是不可能的。如果你看看Python如何存儲局部變量,你可以看到爲什麼。

全局變量存儲在哈希表中,哈希表是動態調整大小的,並且名稱被編譯爲哈希鍵(用Python的說法,即interned字符串)。這使得全球查找比較「慢」,但由於一個需要從其他編譯單元(模塊)名稱查找全局變量,它是必需的:

# a.py 
x = 3 

# b.py 
import a 
a.x = 4 # b needs to know how to find the same x! 

局部變量都存儲在一個固定大小的數組和名稱編譯成數組索引。

當您查看字節碼時,可以看到這個字節碼,它具有LOAD_FAST和STORE_FAST,而LOAD_GLOBAL和STORE_GLOBAL用於全局變量。它也通過你得到的不同例外泄露。 Globals在找不到時產生一個NameError,但未定義的locals被一個空插槽檢測到,從而產生一個UnboundLocalError。

def foo(): 
    a 
    a = 1 
foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in foo 
UnboundLocalError: local variable 'a' referenced before assignment 

def foo(): 
    a = 1 
foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in foo 
NameError: global name 'a' is not defined 

因爲陣列是固定大小的,並且大小被計算而編譯該函數,則不能創建任何另外的本地人。

如果您需要更多「本地人」,您需要將值存儲爲對象的命名屬性或字典中;顯然這也會否定速度優勢。

+1

很好的解釋,+1 – 2011-04-15 12:32:16

相關問題