Alcance variable fuera de las clases.

Mi editor de texto de elección es extensible a través de complementos de Python. Requiere que extienda clases y anule sus métodos. La estructura general se ve similar al fragmento de abajo. Tenga en cuenta que la firma de la función es fija.

ftp_client se supone que es compartido por las instancias de ambas clases.

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

Se supone que ambas clases tienen una variable en común. ¿Cuál es la mejor práctica para compartir variables?

Edición basada en respuesta de madjars:

FtpFileCommand.run se llama primero, ftp_client instancia de ftp_client y funciona como un encanto. FtpFileEventListener.run se llama más tarde y puede hacer referencia a ftp_client perfectamente, pero sigue siendo None . Usando la palabra clave global, ¿agrega la variable como miembro a self ?

Sí, así es exactamente cómo funciona el mundo.

Me parece que lo estás haciendo bien, ya que se hace de esta manera en algunos módulos de la biblioteca estándar de python (entrada de archivo , por ejemplo).

En este código:

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

Usted declara ftp_client como una variable global. Esto significa que vive en el nivel del módulo (donde están sus clases, por ejemplo).

La segunda línea es incorrecta. Quería asignar a la variable global, pero en su lugar, establece un atributo de instancia del mismo nombre.

Debería ser:

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

Pero déjame sugerir un enfoque diferente. Una práctica común es poner esas cosas dentro de la clase, ya que es compartido por todas las instancias de esta clase.

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

Observe que el método no se usa a self por lo que podría ser un método de clase:

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

De esta manera, obtendrá la clase como el primer argumento y puede usarla para acceder al cliente FTP sin usar el nombre de la clase.

Si solo hay una única variable compartida, entonces una solución global es la más sencilla. Pero tenga en cuenta que una variable solo debe declararse con global cuando se asigna a. Si la variable global es un objeto, puede llamar a sus métodos, modificar sus atributos, etc. sin declararlo primero como global.

Una alternativa al uso de variables globales es usar atributos de clase a los que se accede usando métodos de clase. Por ejemplo:

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

¿Podría agregar un constructor a cada clase y luego pasar ftp_client como un argumento?

 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 ... 

Yak … MUCHAS GRACIAS POR ESTO !!!

Usted declara ftp_client como una variable global. Esto significa que vive en el nivel del módulo (donde están sus clases, por ejemplo).

Me estaba costando mucho tratar de escribir mi progtwig “correctamente” donde utilizaba clases y funciones y no podía llamar a ninguna de las variables. Reconocí que global lo haría disponible fuera de la clase. Cuando leí eso, pensé … Si vive fuera de la clase, la variable que necesito recuperar del script py desde el que estoy importando ese módulo sería:

 module.variable 

Y luego dentro de ese módulo, declaré otra variable global para llamarlo desde el script principal … así que ejemplo …

 #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 

Código ModuleB moduleB.py

 class classB(): def functionB(): global moduleB_variable moduleB_variable = retrieve.tacos() 

Espero que mi explicación también ayude a alguien. Soy un principiante con python y luché con esto por un tiempo. En caso de que no estuviera claro … Tenía módulos personalizados separados, compuestos por unos cuantos archivos .py diferentes. Main estaba llamando a moduleA y moduleA estaba llamando a moduleB. Tuve que devolver la variable de la cadena al script principal. El objective de hacerlo de esta manera, era mantener el script principal limpio en su mayor parte, y configurarme para ejecutar tareas repetitivas sin tener que escribir páginas de basura. Básicamente tratando de reutilizar funciones en lugar de escribir un libro.