此代码中classmethod的作用是什么?

72 投票
2 回答
46633 浏览
提问于 2025-04-15 17:18

在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是干什么的。有人能解释一下它的作用以及怎么使用吗?

2 个回答

9

这让我们可以直接在类上调用方法,而不是先创建一个对象再去调用:

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

MyClass._new_instance("blah")
222

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 总是会把类作为它的第一个参数传进去。

使用 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 进行子类化,classmethod 依然可以正常工作,例如:

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

撰写回答