类之外的变量范围

时间:2011-10-13 13:10:08

标签: python class variables namespaces scope

我选择的文本编辑器可以通过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首先被调用,实现ftp_client并且像魅力一样。 FtpFileEventListener.run稍后会被调用,可以完美地引用ftp_client,但它仍然是None。使用global关键字,它是否将变量作为成员添加到self

5 个答案:

答案 0 :(得分:5)

是的,这正是global的工作方式。

在我看来,你做得对,因为它在python标准库的某些模块中以这种方式完成(例如,fileinput)。

答案 1 :(得分: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客户端而不使用类名。

答案 2 :(得分: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()

答案 3 :(得分: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
    ...

答案 4 :(得分: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文件组成。主要是调用moduleA而moduleA正在调用moduleB。我不得不将链中的变量返回到主脚本。我这样做的关键是保持主要脚本在大多数情况下是干净的,并且自己设置执行重复性任务而不必编写垃圾页面。基本上是尝试重用函数而不是写书。