【问题标题】:Variable scope outside of classes类之外的变量范围
【发布时间】:2011-12-06 23:10:00
【问题描述】:

我选择的文本编辑器可以通过 python 插件进行扩展。它需要我扩展类并覆盖它的方法。一般结构看起来类似于下面的 sn-p。请注意,函数签名是固定的。

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 首先被调用,实例化ftp_client 并且像一个魅力一样工作。 FtpFileEventListener.run 稍后调用,可以完美引用ftp_client,但它仍然是None。使用 global 关键字,是否将变量作为成员添加到 self?

【问题讨论】:

  • 回答编辑中的第二个问题:使ftp_client 成为实例属性违背了使用全局变量的目的。新的FTP 对象应在首先将其声明为全局变量后分配给ftp_client 变量。之后,可以从任何地方引用它,而无需将其声明为全局,例如ftp_client.quit().

标签: python class variables namespaces scope


【解决方案1】:

是的,global 就是这样工作的。

在我看来你做得对,因为它在 python 标准库的某些模块中是这样做的(例如fileinput)。

【讨论】:

  • 我根据您的回答编辑了问题,请看一下:)
  • 完成global ftp_client后,您可以使用ftp_client访问它。注意,self.ftp_client 会引用实例的属性,这与全局的ftp_client 不同。
  • 感谢您快速回答。老实说,重新搜索文档也可以帮助我。懒我...
【解决方案2】:

在这段代码中:

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 客户端,而无需使用类名。

【讨论】:

    【解决方案3】:

    如果只有一个共享变量,那么全局变量是最简单的解决方案。但请注意,变量只需要在分配时使用global 声明。如果全局变量是一个对象,你可以调用它的方法,修改它的属性等,而不用先声明它是全局的。

    使用全局变量的替代方法是使用通过类方法访问的类属性。例如:

    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()
    

    【讨论】:

    • 现在这是一个聪明的解决方案!感谢您澄清 global 仅在分配期间需要。我只是为你的答案 +1,因为我觉得从 madjars 答案中删除解决方案标记很顽皮......
    【解决方案4】:

    您能否为每个类添加一个构造函数,然后将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
        ...
    

    【讨论】:

    • 恐怕插件系统可能不接受pzarameters to plugins
    • Xavier Combelle:确切地说,我帖子中给出的结构是固定的,我不允许重写构造函数。
    【解决方案5】:

    牦牛...非常感谢!

    您将 ftp_client 声明为全局变量。这意味着它生活在 模块级别(例如您的类所在的位置)。

    我在尝试“正确”编写程序时遇到了困难,因为我正在使用类和函数并且无法调用任何变量。我认识到 global 将使其在课堂之外可用。当我读到它时,我想......如果它位于类之外,那么我需要从我从中导入该模块的 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。我不得不将变量沿链返回到主脚本。我这样做的目的是在大部分情况下保持主脚本的清洁,并为执行重复性任务做好准备,而不必编写废话页面。基本上是尝试重用函数而不是写一本书。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-03
      • 2016-01-05
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多