2011-10-13 11 views
6

Mi editor de texto de elección es extensible mediante los complementos de python. Me requiere ampliar las clases y anular sus métodos. La estructura general se ve similar al fragmento a continuación. Tenga en cuenta que la firma de la función es fija.Alcance variable fuera de las clases

Se supone que ftp_client se comparte con 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 estas dos clases tienen una variable en común. ¿Cuál es la mejor práctica para compartir variables?

Editar basado en madjars responder:

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

+0

Para responder la segunda pregunta en su edición: hacer 'ftp_client' un atributo de instancia frustra el propósito de usar globales. el nuevo objeto 'FTP' debe asignarse a la variable' ftp_client' después de declararlo como global primero. después de eso, se puede hacer referencia desde cualquier lugar sin la necesidad de declararlo como global, p. 'ftp_client.quit()'. – ekhumoro

Respuesta

5

Sí, eso es exactamente lo global obras.

Me parece que lo está haciendo bien, como se hace de esta manera en algunos módulos de la biblioteca estándar de Python (fileinput, por ejemplo).

+1

He editado la pregunta en función de su respuesta, eche un vistazo :) – fjdumont

+1

Después de hacer 'global ftp_client', puede acceder utilizando' ftp_client'. Tenga cuidado, porque 'self.ftp_client' se referirá al atributo de la instancia, que es diferente del' ftp_client' global. – madjar

+0

Gracias por responder tan rápido. Honestamente, volver a buscar los documentos podría haberme ayudado también. Lazy me ... – fjdumont

0

¿Podría agregar un constructor a cada clase y pasar ftp_client como 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 
    ... 
+0

Me temo que el sistema de complementos puede no aceptar pzarameters a los complementos –

+0

Xavier Combelle: exactamente, la estructura dada en mi publicación es fija y no puedo anular los constructores. – fjdumont

3

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

Una alternativa para usar variables globales es usar atributos de clase a los que se accede usando classmethods. 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() 
+0

¡Ahora que es una solución inteligente! Gracias por aclarar que 'global' solo se requiere durante la asignación. Solo respondí +1 en respuesta porque me siento travieso al eliminar la marca de solución de la respuesta de madjars ... – fjdumont

4

En este código:

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

se 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ías asignar a la variable global, pero en su lugar estableces un atributo de instancia del mismo nombre.

Debería ser:

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

Pero permítanme sugerir un enfoque diferente. Una práctica común es poner tales cosas dentro de la clase, ya que es compartida 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 

en cuenta que el método no utiliza self por lo que bien 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 primer argumento y se puede utilizar para acceda al cliente FTP sin usar el nombre de clase.

0

Yak ... ¡MUCHAS GRACIAS POR ESTO!

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

Estaba pasando un momento difícil tratando de escribir mi programa "correctamente" cuando estoy utilizando 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, entonces la variable que necesito para recuperar a partir del guión py que estoy importando a este módulo sería:

module.variable 

Y entonces dentro de ese módulo , declaré otra variable global a llamarlo desde el script principal ... así ... 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 

ModuleB código moduleB.py

class classB(): 

    def functionB(): 

     global moduleB_variable 
     moduleB_variable = retrieve.tacos() 

Espero que mi explicación también ayuda 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 formados por unos pocos archivos .py diferentes. Main llamaba moduleA y moduleA llamaba al móduloB. Tuve que devolver la variable en la cadena al guión principal. El objetivo de mí hacerlo de esta manera, era mantener limpia la secuencia principal en su mayor parte, y prepararme para ejecutar tareas repetitivas sin tener que escribir páginas de basura. Básicamente tratando de reutilizar funciones en lugar de escribir un libro.

Cuestiones relacionadas