@classmethod x @staticmethod

Um amigo me mandou um email perguntando uma dúvida sobre um decorator de Python…

@classmethod
def unpack (cls, raw, prev=None):
  return cls(raw=raw, prev=prev)

Pode destrinchar isto para mim? classmethod é uma função built-in do Python. Significa que dentro do método eu substituo cls por classmetho?

Oi,

Segundo o que vi em algumas referências, o @classmethod
é igual ao @staticmethod, ambos são para definir um método estático dentro de uma classe[1][2]. Um método estático não é nada mais que uma função definida dentro de uma classe. Não precisa criar uma instância de uma classe para chamar ele.

Por exemplo, supondo essa classe:

class A:
    def __init__(self):
        pass

    def foo(self):
        pass

    @staticmethod
    def boo():
        pass

O método foo não é estático então deveria ser chamado a partir de uma instância:

obj = A()
# Chamando um método não estático a partir de uma instância
obj.foo()

#Chamando um método estático a partir de uma instância
obj.boo()

Já o método boo é estático então não precisa ser chamado de uma instância, mas pode ser, apesar que não seja uma boa prática.

obj = A()
# Chamando um método estático a partir de uma classe
A.boo()

# Chamando um método não estático a partir de uma classe
A.foo()
Traceback (most recent call last):
File "input", line 1, in
TypeError: unbound method foo() must be called with A instance as first argument
(got nothing instead)

Como pode ver, conseguimos chamar um método estático a partir da classe, mas não um não estático.

Voltando a @classmethod e @staticmethod… O decorador @staticmethod permite criar métodos estáticos e esses métodos não podem ser sobrescritos pelas subclasses. Ele é imutável.

Já os métodos com o decorador @classmethod permite criar métodos estáticos que podem ser sobrescritos pelas subclasses. Isto é porque o primeiro parâmetro das funções que tem o @classmethod tem que ser sempre cls (classe)[3].

Aparentemente esse método que você enviou é uma factory[4]. Métodos que são usados para criar instância de outras classes.

O exemplo que você me enviou:

   @classmethod
   def unpack (cls, raw, prev=None):
       return cls(raw=raw, prev=prev)

Segundo o que eu disse, cls é um tipo de classe e o método retorna uma instância dessa classe no qual é passado os outros dois parâmetros para o construtor dela.

Abraço.

[1] http://jfine-python-classes.readthedocs.org/en/latest/decorators.html
[2] http://stackoverflow.com/questions/12179271/python-classmethod-and-staticmethod-for-beginner
[3] http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
[4] https://pt.wikipedia.org/wiki/Factory_Method


Warning: Missing argument 1 for cwppos_show_review(), called in /home/rodrigolira/blog.rodrigolira.net/wp-content/themes/flat/content-single.php on line 29 and defined in /home/rodrigolira/blog.rodrigolira.net/wp-content/plugins/wp-product-review/includes/legacy.php on line 18