2009-12-23 16 views
28

In django.utils.tree.py:Cosa significa classmethod fare in questo codice?

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) 

Non so cosa classmethod fa in questo esempio di codice. Qualcuno può spiegare cosa fa e come usarlo?

+1

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

+3

mi affascina sempre come una domanda rimane valida e sano anche dopo 7 anni !! :) – NoobEditor

risposta

112

classmethod è un descrittore, avvolgendo una funzione, e si può chiamare l'oggetto risultante su una classe o (equivalentemente) un'istanza thereof:

>>> 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'>,) 

come si vede, se si definisce direttamente o con la sintassi decoratore, e se lo chiamate sulla classe o l'istanza, il classmethod riceve sempre la classe come primo parametro.

Uno dei principali usi di classmethod è quello di definire "costruttori alternativi":

>>> 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') 

Ora, se si sottoclasse y, il classmethod continua a lavorare, ad esempio:

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

Nizza illustrazione @AlexMartelli –

+0

Questo non è un costruttore di altenative, questo è un metodo di fabbrica. – t3chb0t

4

Esso permette di chiamare il metodo sulla classe anziché un oggetto:

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

MyClass._new_instance("blah") 
+1

E 'anche più comunemente usato come un decoratore: '@classmethod def _new_instance (cls, bla):' –

Problemi correlati