Variable scope outside of classes
Solution 1
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).
Solution 2
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.
Solution 3
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()
fjdumont
Updated on October 07, 2020Comments
-
fjdumont over 3 years
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, instanciatesftp_client
and works like a charm.FtpFileEventListener.run
is called later and, can referenceftp_client
perfectly but it is stillNone
. Using the global keyword, does it add the variable as a member toself
? -
Xavier Combelle over 12 yearsI'm afraid that the plugin system may not accept pzarameters to plugins
-
fjdumont over 12 yearsXavier Combelle: exactly, the structure given in my post is fixed and I am not allowed to override the constructors.
-
fjdumont over 12 yearsI edited the question based on your answer, please have a look :)
-
madjar over 12 yearsAfter doing
global ftp_client
, you can access it usingftp_client
. Be careful, becauseself.ftp_client
will refer to the attribute of the instance, which is different of the globalftp_client
. -
fjdumont over 12 yearsThanks for answering that quickly. Honestly, reasearching the docs could've helped me as well. Lazy me...
-
fjdumont over 12 yearsNow that's a smart solution! Thanks for clarifying that
global
is only required during assignment. I just +1'd your answer because I feel naughty removing the solution mark from madjars answer...