2012-10-08 37 views
4

我有一個Python應用程序,如下所示:Python - 爲什麼這個類的變量沒有在方法中定義?

global_counter = 0 
connections = {} 

class SocketHandler(): 
    currentid = 0 
    def open(self): 
     global global_counter 
     global connections 
     currentid = global_counter 
     global_counter += 1 
     connections[currentid] = self 
     print "WebSocket " + str(currentid) + " opened" 

    def on_close(self): 
     global connections 
     print "WebSocket " + str(currentid) + " closed" 
     del connections[currentid] 

,我發現了錯誤:

NameError: global name 'currentid' is not defined 

上的線「開」和「on_close」在那裏我打印,我打開/關閉連接。我在課堂上定義它,爲什麼它不在範圍內。另外,我已經讀過使用全局變量是不好的,但我沒有看到解決這個問題的方法。有人能指出我應該做什麼嗎?謝謝。

+0

使用self.currentid –

回答

7

你不必裏面的方法來屬性隱式訪問,在Python。

像線currentid裸名稱:

del connections[currentid] 

看起來總是一個名字在當地的功能範圍,然後在每個封閉功能範圍,試圖在全球模塊範圍(之前,然後查找在建作爲最後的手段)。 currentid是一個類屬性,它不會在任何這些作用域中找到。

要在Python中查找屬性,您需要指定一個對象來查找。儘管查找協議意味着對象不一定具有屬性本身;屬性查找將回退到您指定的對象的類(如果涉及到繼承,則返回基類)。

所以這會工作:

del connections[self.currentid] 

不過,我不認爲你的代碼的其餘部分是做什麼的,你想,不是。這條線在open方法:

currentid = global_counter 

不設置你的SocketHandler對象的屬性currentid。指定爲裸姓名總是分配給本地變量,除非您明確聲明global(您似乎知道這一點,因爲您已使用關鍵字global)。所以在open方法中,currentid是一個局部函數變量;它的價值在open方法的末尾丟失。

實際上,您的SocketHandler對象根本沒有currentid屬性(除非有更多代碼未顯示給我們)。將currentid = 0放在類塊中並不會給出所有SocketHandler實例的currentid屬性。它給出了SocketHandler類別本身的一個屬性currentid;這正如def open(self):塊在類對象上創建open屬性(存儲函數),而不是在每個單獨的實例上創建。

on_close方法讀self.currentid將無法​​找到對象self一個currentid屬性,所以Python會看類self這是SocketHandler。該對象確實的值爲currentid,因此讀取self.currentid的結果將爲0,無論您以前是否在SocketHandler上運行過open

如果意圖將currentid作爲一個實例變量存儲在每個SocketHandler,然後在open線將需要:

self.currentid = global_counter 

此分配給對象的currentid屬性由self提及。您還需要將您方法中的所有其他引用currentid更改爲self.currentid

+0

這真的很清楚,謝謝你寫出來。 – Lylax

2

currentid應該是self.currentid,因爲它是一個類變量。

+0

這很合理,謝謝! – Lylax

+0

這是爲什麼這麼多upvoted? - 上面的實例中的代碼將不再與NameError打破,但如果僅進行此替換,則會發生嚴重的邏輯錯誤。 – jsbueno

+0

@jsbueno:你是什麼意思?唯一被修改的其他變量是全局變量。 – Blender

0

currentid是實例屬性,因此使用self.currentid,而不是currentid

def on_close(self): 
     global connections 
     print "WebSocket " + str(self.currentid) + " closed" 
     del connections[self.currentid] 
相關問題