2011-10-13 72 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。我不得不将链上的变量返回到主脚本。我这样做的要点是保持主要脚本的大部分清洁,并为自己设置执行重复性任务而不必编写垃圾页面。基本上试图重用函数而不是写书。