Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable scope outside of classes

My text editor of choice is extensible through python plugins. It requires me to extend classes and override its methods. The general structure looks similar the snippet below. Note that the function signature is fixed.

ftp_client is supposed to be shared by instances of both classes.

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

Both of these classes are supposed to have one variable in common. What is the best practice in order to share variables?

Edit based on madjars answer:

FtpFileCommand.run is called first, instanciates ftp_client and works like a charm. FtpFileEventListener.run is called later and, can reference ftp_client perfectly but it is still None. Using the global keyword, does it add the variable as a member to self?

like image 312
fjdumont Avatar asked Oct 13 '11 13:10

fjdumont


People also ask

Which variable can access outside of the class?

If you want to use that variable even outside the class, you must declared that variable as a global. Then the variable can be accessed using its name inside and outside the class and not using the instance of the class.

Can you access a public variable outside of it's class?

Private and Public Access You can read or write to the variable from anywhere within the module, class, or structure, but not from outside it.

Can variables be declared outside a class in Java?

Instance variables are non-static variables and are declared in a class outside of any method, constructor, or block. As instance variables are declared in a class, these variables are created when an object of the class is created and destroyed when the object is destroyed.

Can a variable be accessed outside of its scope?

The var keyword is limited to function scope, meaning that new scope can only be created inside functions. Function and block scopes can be nested. In such a situation, with multiple nested scopes, a variable is accessible within its own scope or from inner scope. But outside of its scope, the variable is inaccessible.


3 Answers

Yep, that's exactly how global works.

It seems to me you are doing it right, as it's done this way in some modules of the python standard library (fileinput, for example).

like image 179
madjar Avatar answered Oct 22 '22 07:10

madjar


In this code:

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

you declare ftp_client as a global variable. This means it lives at the module level (where your classes are for example).

The second line is wrong. You wanted to assign to the global variable but instead you set an instance attribute of the same name.

It should be:

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

But let me suggest a different approach. A common practice is to put such stuff inside the class, since it is shared by all instances of this class.

class FtpFileCommand(sublime_plugin.TextCommand):
  ftp_client = None

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

Notice that the method doesn't use self so it might as well be a class method:

class FtpFileCommand(sublime_plugin.TextCommand):
  ftp_client = None

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

This way you will get the class as the first argument and you can use it to access the FTP client without using the class name.

like image 45
yak Avatar answered Oct 22 '22 07:10

yak


If there's only a single shared variable, then a global is the simplest solution. But note that a variable only needs to be declared with global when it is being assigned to. If the global variable is an object, you can call its methods, modify its attributes, etc without declaring it as global first.

An alternative to using global variables is to use class attributes which are accessed using classmethods. For example:

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()
like image 3
ekhumoro Avatar answered Oct 22 '22 08:10

ekhumoro