Working @classmethod

3

I'd like to get a better understanding of the @classmethod annotation of Python.

Briefly, it works as a second constructor alternative. But what are the benefits? When to use?

@classmethod
def from_teste(cls, teste):

How does cls work?

    
asked by anonymous 08.04.2015 / 21:03

1 answer

8

By default every method created in a class belongs to the object. This means that an instance of the object is required to call a method, and this instance is usually associated with the first parameter of the function (which is called self ). Even the __init__ method, called during object construction, already assumes that the object exists and is accessible through the self parameter.

class Foo(object):
    def __init__(self):
        pass # self é o objeto sendo criado
    def bar(self, a, b, d):
        pass # self é o objeto

foo = Foo()
foo.bar(1,2,3) # implicitamente passa "foo" como 1º argumento para "bar"
fn = foo.bar   # fn aqui é um bound method, ligado a "foo"
fn(1,2,3)      # Ainda passa "foo" como 1º argumento para "bar"

To create methods that belong to the class, not to the object, you can use the @staticmethod or @classmethod decorators. Both are similar, although the former does not refer to the class and the latter does so (similarly to the common method, although in this case it is called cls instead of self ).

class Foo(object):
    @staticmethod
    def bar(a, b, c):
        pass
    @classmethod
    def baz(cls, a, b, c):
        pass

Foo.bar(1,2,3) # Os argumentos são 1, 2 e 3
Foo.baz(1,2,3) # Os argumentos são Foo, 1, 2 e 3

x = Foo() # Também se pode chamar métodos de classe a partir de uma instância
x.bar(1,2,3) # Os argumentos são 1, 2 e 3
x.baz(1,2,3) # Os argumentos são Foo, 1, 2 e 3

The main difference between @classmethod and @staticmethod is that the first can be inherited in order to do something useful. For although both are "inheritable," the former can take the class into consideration in its function, and the latter does not (since it has no reference to the class being used).

class Foo(object):
    @staticmethod
    def bar():
        print Foo   # Não há referência à classe, então só se pode acessá-la pelo nome
    @classmethod
    def baz(cls):
        pprint cls  # Há referência explícita à classe

class Bar(Foo):
    pass

Bar.bar() # imprime Foo
Bar.baz() # imprime Bar

A static / class method can be used for anything, but it makes more sense to use it for things that are related to the class being defined (otherwise, put it in a class, not directly in the module ?). One possibility is to use it as factory , customizing the creation of objects not necessarily of the same class (for example using subclasses when appropriate), or even when the class is the same, varying the parameters received. But there are many others. Personally, I do not recall situations in which a class method was useful to me [in Python], although I vaguely remember having already used it.

    
08.04.2015 / 22:33