Что classmethod делает в этом коде?

В django.utils.tree.py:

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)

Я не знаю что classmethod делает в этом примере кода. Кто-то может объяснить, что это делает и как использовать его?

46
задан Jason Plank 2 August 2011 в 16:44
поделиться

2 ответа

classmethod - это декоратор, обертывающий функцию, и вы можете вызвать результирующий объект на классе или (эквивалентно) на его экземпляре:

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

Как видите, определяете ли вы его непосредственно или с помощью синтаксиса декоратора, и вызываете ли вы его на классе или на экземпляре, одноклассный метод classmethod всегда получает класс в качестве своего первого аргумента.

Одно из основных применений одноклассного метода - это определение альтернативных конструкторов:

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

Теперь, если вы используете подкласс y, одноклассный метод продолжает работать, например:

>>> class k(y):
...   def __repr__(self):
...     return 'k(%r)' % self.s.upper()
...
>>> k1 = k.fromlist(['za','bu'])
>>> k1
k('ZA,BU')
170
ответ дан 26 November 2019 в 19:59
поделиться

Это позволяет вызвать метод на классе вместо объекта:

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

MyClass._new_instance("blah")
8
ответ дан 26 November 2019 в 19:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: