2009-12-23 12 views
28

En django.utils.tree.py:¿Qué hace classmethod en este código?

def _new_instance(cls, children=None, connector=None, negated=False): 
     obj = Node(children, connector, negated) 
     obj.__class__ = cls 
     return obj 
    _new_instance = classmethod(_new_instance) 

No sé lo que classmethod hace en este ejemplo de código. ¿Alguien puede explicar lo que hace y cómo usarlo?

+1

víctima: http://stackoverflow.com/questions/38238/what-are-class-methods-in-python-for –

+3

¡Siempre me fascina cómo una pregunta sigue siendo válida y sensata incluso después de 7 años! :) – NoobEditor

Respuesta

112

classmethod es un descriptor, envolviendo una función, y se puede llamar el objeto resultante en una clase o (equivalentemente) una instancia del mismo:

>>> class x(object): 
... def c1(*args): print 'c1', args 
... c1 = classmethod(c1) 
... @classmethod 
... def c2(*args): print 'c2', args 
... 
>>> inst = x() 
>>> x.c1() 
c1 (<class '__main__.x'>,) 
>>> x.c2() 
c2 (<class '__main__.x'>,) 
>>> inst.c1() 
c1 (<class '__main__.x'>,) 
>>> inst.c2() 
c2 (<class '__main__.x'>,) 

como se ve, ya sea que lo definen directamente o con la sintaxis de decorador, y si usted lo llama en la clase o la instancia, el classmethod siempre recibe la clase como su primer argumento.

Uno de los principales usos de classmethod es definir "constructores alternativos":

>>> class y(object): 
... def __init__(self, astring): 
...  self.s = astring 
... @classmethod 
... def fromlist(cls, alist): 
...  x = cls('') 
...  x.s = ','.join(str(s) for s in alist) 
...  return x 
... def __repr__(self): 
...  return 'y(%r)' % self.s 
... 
>>> y1 = y('xx') 
>>> y1 
y('xx') 
>>> y2 = y.fromlist(range(3)) 
>>> y2 
y('0,1,2') 

Ahora bien, si subclase y, la classmethod sigue trabajando, por ejemplo:

>>> class k(y): 
... def __repr__(self): 
...  return 'k(%r)' % self.s.upper() 
... 
>>> k1 = k.fromlist(['za','bu']) 
>>> k1 
k('ZA,BU') 
+2

Bonita ilustración @AlexMartelli –

+0

Este no es un constructor altenativo, este es un método de fábrica. – t3chb0t

4

Esto hace que sea posible para llamar al método en la clase en lugar de un objeto:

class MyClass(object): 
    def _new_instance(cls, blah): 
     pass 
    _new_instance = classmethod(_new_instance) 

MyClass._new_instance("blah") 
+1

También es más comúnmente utilizado como decorador: '@método de clase def _new_instance (cls, bla):' –

Cuestiones relacionadas