255 votos

¿Cuáles son los métodos de clases en Python para?

Estoy aprendiendo Python y mi más reciente lección fue que Python no es Java, y por lo acabo de pasar un tiempo convirtiendo a todos mis métodos de la Clase en funciones.

Ahora me doy cuenta de que no tengo necesidad de utilizar los métodos de la Clase para lo que yo iba a hacer con static métodos en Java, pero ahora no estoy seguro de que cuando yo haría uso de ellos. Todos los consejos que puedo encontrar sobre Python métodos de la Clase es a lo largo de las líneas de los novatos como yo, debe alejarse de ellos, y la documentación estándar es de lo más opaco cuando se habla de ellos.

¿Alguien tiene un buen ejemplo del uso de un método de Clase en Python o, al menos, alguien me puede decir cuando los métodos de la Clase pueden ser razonablemente utilizados?

181voto

John Millikin Puntos 86775

Métodos de la clase son para cuando usted necesita para tener métodos que no son específicas para ninguna instancia en particular, pero aún así involucrar a la clase de alguna manera. Lo más interesante de ellos es que no puede ser reemplazado por subclases, algo que simplemente no es posible en Java los métodos estáticos o Python del módulo de funciones de nivel.

Si usted tiene una clase MyClass, y un nivel de módulo de función que opera en Miclase (la fábrica, la dependencia de la inyección de código auxiliar, etc.), hacen que sea un classmethod. A continuación, estará disponible en las subclases.

64voto

AmanKow Puntos 732

Métodos de fábrica (alternativa constructores) son, de hecho, un ejemplo clásico de los métodos de la clase.

Básicamente, los métodos de la clase son adecuados en cualquier momento te gustaría tener un método que, naturalmente, cabe en el espacio de nombres de la clase, pero no está asociado con una instancia concreta de la clase.

Como un ejemplo, en el excelente unipath módulo:

Directorio actual

  • Path.cwd()
    • Retorno de la corriente real de directorio; p.ej., Path("/tmp/my_temp_dir"). Este es un método de clase.
  • .chdir()
    • Hacer auto el directorio actual.

Como el directorio actual es el proceso de ancho, la cwd método no tiene ninguna instancia en particular con la que deben ser asociados. Sin embargo, el cambio cwd para el directorio de una determinada Path de instancia debe ser, de hecho, un método de instancia.

Hmmm... como Path.cwd() en efecto, devuelven un Path de instancia, supongo que puede ser considerada como un método de fábrica...

48voto

Brandon Rhodes Puntos 21188

Piénselo de esta manera: normal métodos son útiles para ocultar los detalles del envío: puede escribir myobj.foo() sin preocuparse de si el foo() método es implementado por la myobj de clase del objeto o de una de sus clases para los padres. Métodos de la clase son exactamente análoga a la presente, sino con el objeto de clase de lugar: se permiten llamar a MyClass.foo() sin tener que preocuparse de si foo() está implementado especialmente por MyClass debido a la necesidad de su propia versión especializada, o si se trata de dejar a sus padres de clase manejar la llamada.

Métodos de la clase son esenciales cuando está haciendo el set-up o cálculo que precede a la creación de una instancia real, ya que hasta la instancia existe obviamente, no puede utilizar la instancia como el envío de punto para sus llamadas de método. Un buen ejemplo puede verse en la SQLAlchemy código fuente, echa un vistazo a las dbapi() método de clase en el siguiente enlace:

http://hg.sqlalchemy.org/sqlalchemy/file/230819db717a/lib/sqlalchemy/dialects/mssql/pymssql.py

Se puede ver que el dbapi() método, que un servidor de base de datos utiliza para importar el proveedor de base de datos específica biblioteca necesidades de la demanda, es un método de clase debido a que se debe ejecutar antes de instancias de una determinada conexión de base de datos empezar a crear - pero eso no puede ser una simple función o función estática, porque ellos quieren que sea capaz de llamar a otros, el apoyo a métodos que podrían también deben ser escritos más específicamente en las subclases que en su clase padre. Y si te envío a una función o estático de la clase, luego se "olvida" y perder el conocimiento acerca de la clase que está haciendo la inicialización.

29voto

Marvo Puntos 5444

Recientemente he querido un muy ligeros de peso de registro de clase, que sería la salida de cantidades variables de salida en función del nivel de registro que se podría establecer mediante programación. Pero yo no quiero crear una instancia de la clase cada vez que quería a la salida de un mensaje de depuración o de error o de advertencia. Pero yo también quería encapsular el funcionamiento de esta utilidad de registro y hacer que sea reutilizable sin la declaración de cualquier globales.

Así que utiliza las variables de la clase y el @classmethod decorador para lograr esto.

Con mi simple Registro de clase, yo podría hacer lo siguiente:

Logger._level = Logger.DEBUG

Entonces, en mi código, si quería escupir un montón de información de depuración, yo simplemente tenía que código

Logger.debug( "this is some annoying message I only want to see while debugging" )

Errores se podrían poner con

Logger.error( "Wow, something really awful happened." )

En la "producción" medio ambiente", puedo especificar

Logger._level = Logger.ERROR

y ahora, sólo el mensaje de error será la salida. El mensaje de depuración no será impreso.

Aquí está mi clase:

class Logger :
    ''' Handles logging of debugging and error messages. '''

    DEBUG = 5
    INFO  = 4
    WARN  = 3
    ERROR = 2
    FATAL = 1
    _level = DEBUG

    def __init__( self ) :
        Logger._level = Logger.DEBUG

    @classmethod
    def isLevel( cls, level ) :
        return cls._level >= level

    @classmethod
    def debug( cls, message ) :
        if cls.isLevel( Logger.DEBUG ) :
            print "DEBUG:  " + message

    @classmethod
    def info( cls, message ) :
        if cls.isLevel( Logger.INFO ) :
            print "INFO :  " + message

    @classmethod
    def warn( cls, message ) :
        if cls.isLevel( Logger.WARN ) :
            print "WARN :  " + message

    @classmethod
    def error( cls, message ) :
        if cls.isLevel( Logger.ERROR ) :
            print "ERROR:  " + message

    @classmethod
    def fatal( cls, message ) :
        if cls.isLevel( Logger.FATAL ) :
            print "FATAL:  " + message

Y una parte de código que comprueba que sólo un poco:

def logAll() :
    Logger.debug( "This is a Debug message." )
    Logger.info ( "This is a Info  message." )
    Logger.warn ( "This is a Warn  message." )
    Logger.error( "This is a Error message." )
    Logger.fatal( "This is a Fatal message." )

if __name__ == '__main__' :

    print "Should see all DEBUG and higher"
    Logger._level = Logger.DEBUG
    logAll()

    print "Should see all ERROR and higher"
    Logger._level = Logger.ERROR
    logAll()

26voto

Aaron Maenpaa Puntos 39173

Constructores alternativos son el ejemplo clásico.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X