2011-10-13 46 views
6

我選擇的文本編輯器可以通過python插件擴展。它要求我擴展類並覆蓋它的方法。一般結構看起來類似下面的代碼片段。請注意,函數簽名是固定的。變量範圍以外的類

ftp_client應該由兩個類的實例共享。

ftp_client = None 

class FtpFileCommand(sublime_plugin.TextCommand): 
    def run(self, args): 
    global ftp_client # does it reference the variable of the outer scope? 
    self.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

class FtpFileEventListener(sublime_plugin.EventListener): 
    def run(self, args): 
    global ftp_client # same for this 
    self.ftp_client.quit() # 

這兩個類都應該有一個共同的變量。爲了分享變量,最佳做法是什麼?

編輯基於madjars回答:

FtpFileCommand.run首次調用,instanciates ftp_client和工程就像一個魅力。稍後調用FtpFileEventListener.run,完全可以參考ftp_client,但它仍然是None。使用全局關鍵字,是否將變量作爲成員添加到self

+0

要回答你的編輯第二個問題:做'ftp_client'實例屬性違背了使用全局變量的目的。在聲明全局優先後,新的'FTP'對象應該分配給'ftp_client'變量。之後,它可以從任何地方被引用,而不需要將其聲明爲全局的,例如, 'ftp_client.quit()'。 – ekhumoro

回答

5

沒錯,這正是如何global作品。

在我看來,你正在做的是正確的,因爲它是在Python標準庫的一些模塊(例如fileinput)中以這種方式完成的。

+1

我編輯根據您的回答這個問題,請看看:) – fjdumont

+1

做'全球ftp_client'後,您可以使用'ftp_client'訪問它。要小心,因爲'self.ftp_client'將引用實例的屬性,這與全局'ftp_client'不同。 – madjar

+0

感謝您快速回答。老實說,研究文檔也可以幫助我。懶惰的我... – fjdumont

0

你可以給每個類添加一個構造函數,然後通過ftp_client作爲參數嗎?

class FtpFileCommand(sublime_plugin.TextCommand): 
    ... 
    def __init__(self, ftp_client): 
     self.ftp_client = ftp_client 
    ... 

class FtpFileEventListener(sublime_plugin.EventListener): 
    ... 
    def __init__(self, ftp_client): 
     self.ftp_client = ftp_client 
    ... 
+0

恐怕插件系統可能不接受pzarameters到插件 –

+0

澤維爾Combelle:準確地說,在我的崗位給出的結構是固定的,我不能覆蓋的構造。 – fjdumont

3

如果只有一個共享變量,那麼全局是最簡單的解決方案。但請注意,只有在分配變量時才需要使用global來聲明變量。如果全局變量是一個對象,你可以調用它的方法,修改它的屬性等,而不必將它聲明爲全局優先。

使用全局變量的替代方法是使用classmethods訪問的類屬性。例如:

class FtpFile(object): 
    _client = None 

    @classmethod 
    def client(cls): 
     return cls._client 

    @classmethod 
    def setClient(cls, client): 
     cls._client = client 

class FtpFileCommand(FtpFile, sublime_plugin.TextCommand): 
    def run(self, args): 
     client = self.client() 

class FtpFileEventListener(FtpFile, sublime_plugin.EventListener): 
    def run(self, args): 
     client = self.client() 
+0

現在,這是一個聰明的解決方案!感謝您澄清,只有在分配過程中才需要'global'。我剛剛爲你的答案+1,因爲我覺得淘氣解決方案標記從madjars回答... – fjdumont

4

在此代碼:

global ftp_client # does it reference the variable of the outer scope? 
self.ftp_client = ftplib.FTP('foo') 

聲明ftp_client爲全局變量。這意味着它生活在模塊級別(例如你的類)。

第二行是錯誤的。你想分配給全局變量,而是設置一個同名的實例屬性。

它應該是:

global ftp_client 
ftp_client = ftplib.FTP('foo') 

但讓我提出一個不同的方法。通常的做法是將這些東西放在類中,因爲它被這個類的所有實例共享。

class FtpFileCommand(sublime_plugin.TextCommand): 
    ftp_client = None 

    def run(self, args): 
    FtpFileCommand.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

注意,該方法不使用self所以它很可能會成爲一個類的方法:

class FtpFileCommand(sublime_plugin.TextCommand): 
    ftp_client = None 

    @classmethod 
    def run(cls, args): 
    cls.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

這樣,您將獲得類作爲第一個參數,你可以用它來訪問FTP客戶端而不使用類名稱。

0

犛牛...謝謝你這麼多的這個!

您聲明ftp_client爲全局變量。這意味着它的模塊級別爲 (例如,你的類是這樣的)。

我很困難的時候試圖寫我的程序「正常」,我正在利用類和函數,並且無法調用任何變量。我意識到,全球範圍內可以在課堂之外提供。當我讀到我以爲,如果它生活類之外,那麼我需要從我進口該模塊從PY腳本檢索的變量是:

module.variable 

然後該模塊內,我聲明另一個全局變量從主腳本...所以例如叫它...

#Main Script main.py 
import moduleA 

print(moduleA.moduleA.variable) 


#ModuleA code moduleA.py 
import moduleB 

class classA(): 

    def functionA(): 

     global moduleA_variable 
     call.something.from.moduleB.classB.functionB() 
     moduleA_variable = moduleB.moduleB_variable 

ModuleB代碼moduleB.py

class classB(): 

    def functionB(): 

     global moduleB_variable 
     moduleB_variable = retrieve.tacos() 

我希望我的解釋也可以幫助別人。我是一名Python初學者,爲此苦苦掙扎了一段時間。如果不清楚......我有單獨的自定義模塊,由幾個不同的.py文件組成。 Main調用moduleA,moduleA調用moduleB。我不得不將鏈上的變量返回到主腳本。我這樣做的要點是保持主要腳本的大部分清潔,併爲自己設置執行重複性任務而不必編寫垃圾頁面。基本上試圖重用函數而不是寫書。