¿Cuándo debo usar @classmethod y cuándo def method(self)?
Al integrar una aplicación Django que no he usado antes, encontré dos formas diferentes de definir funciones en clases. El autor parece usarlos a ambos muy intencionalmente. El primero es uno que yo mismo uso mucho:
class Dummy(object):
def some_function(self,*args,**kwargs):
do something here
self is the class instance
El otro es uno que no uso, principalmente porque no entiendo cuándo usarlo, y para qué:
class Dummy(object):
@classmethod
def some_function(cls,*args,**kwargs):
do something here
cls refers to what?
En los documentos de Python, el decorador classmethod
se explica con esta oración:
Un método de clase recibe la clase como implícita primer argumento, solo como un método de instancia recibe la instancia.
Así que supongo que cls
se refiere a Dummy
en sí (el class
, no la instancia). No entiendo exactamente por qué existe esto, porque siempre podría hacer esto:
type(self).do_something_with_the_class
¿Es esto solo por el bien de la claridad, o me perdí la parte más importante: cosas espeluznantes y fascinantes que no se podrían hacer sin ella?
2 answers
Tu suposición es correcta-entiendes cómo classmethod
s trabajo.
El porqué es que estos métodos pueden ser invocados tanto en una instancia COMO en la clase (en ambos casos, el objeto de clase será pasado como primer argumento):
class Dummy(object):
@classmethod
def some_function(cls,*args,**kwargs):
print cls
#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()
Sobre el uso de estos en instancias: Hay al menos dos usos principales para llamar a un classmethod en una instancia:
-
self.some_function()
llamará a la versión desome_function
en el tipo real deself
, en lugar de la clase en que esa llamada aparece (y no necesitará atención si se cambia el nombre de la clase); y - En los casos en que
some_function
es necesario implementar algún protocolo, pero es útil llamar solo al objeto de la clase.
La diferencia con staticmethod
: Hay otra forma de definir métodos que no acceden a datos de instancia, llamada staticmethod
. Que crea un método que no recibe un primer argumento implícito en absoluto; en consecuencia, no se pasará ninguna información sobre el instancia o clase en la que fue llamado.
In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)
In [7]: Foo.some_static(1)
Out[7]: 2
In [8]: Foo().some_static(1)
Out[8]: 2
In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)
In [10]: Bar.some_static(1)
Out[10]: 2
In [11]: Bar().some_static(1)
Out[11]: 2
El uso principal que he encontrado para ello es adaptar una función existente (que no espera recibir un self
) para que sea un método en una clase (u objeto).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 17:11:48
Si agregas decorator @classmethod, eso significa que vas a hacer que ese método sea un método estático de java o C++. (método estático es un término general Supongo ;) ) Python también tiene @staticmethod. y la diferencia entre classmethod y staticmethod es si se puede acceso a la clase o variable estática usando el propio argumento o classname.
class TestMethod(object):
cls_var = 1
@classmethod
def class_method(cls):
cls.cls_var += 1
print cls.cls_var
@staticmethod
def static_method():
TestMethod.cls_var += 1
print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()
#construct instances
testMethodInst1 = TestMethod()
testMethodInst2 = TestMethod()
#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()
Todas esas clases aumentan cls.cls_var por 1 e imprimirlo.
Y cada clase usando el mismo nombre en el mismo ámbito o las instancias construidas con estas clases van a compartir esos métodos. Sólo hay un método de prueba.cls_var y también hay un solo método de prueba.class_method (), TestMethod.static_method ()
Y una pregunta importante. por qué estos métodos serían necesarios.
Classmethod o staticmethod es útil cuando haces esa clase como una fábrica o cuando tienes que inicializar tu clase solo una vez. como abrir archivo una vez, y usando el método de alimentación para leer el archivo línea por línea.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 17:07:15