Funcionamento @classmethod

Asked

Viewed 5,098 times

9

I would like to better understand the @classmethod annotation of Python.

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

@classmethod
def from_teste(cls, teste):

How the cls ?

  • "works as a second alternative to constructor" what so? Class methods (and static methods) have no relation to constructors, as far as I know... (one class method - the __new__ - has involvement with the creation of objects, but the rest has nothing to do) P.S. I just realized that some people use class methods as alternative builders ("factory" methods, actually), and this is ok, only the concept is much broader than that.

1 answer

17


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

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 class, and not to the object, you can use the decorators @staticmethod or @classmethod. Both are similar, although the former makes no reference to the class and the latter does (similarly to the common method, although in this case it is agreed to call 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 may be inherited in order to do something useful. For although both are "inheritable", the former may take the class into account in exercising its function, and the latter not (for 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 class/static 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 why put it in a class, and 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 received parameters. But there are many others. Personally, I don’t remember situations where a class method was useful to me [in Python], although I vaguely remember having used it already.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.