@classmethod的位置

时间:2012-02-12 09:07:05

标签: python decorator python-2.7

位于python源代码中的decorator classmethod的源代码在哪里。具体来说,我无法找到它在2.7.2版本中定义的确切文件

2 个答案:

答案 0 :(得分:17)

我没有回答你的问题 - 但是下面显示了用纯Python编写的等同于classmethod的装饰器 - 因为源代码中的那个是在C中,在Python-2.7.2/Objects/funcobject.c内米什纳提出了他的答案。

因此,类方法的想法是使用“描述符”机制,如Python's data model中所述 - 并使其成为__get__方法返回一个函数对象,当被调用时,将使用预先填充的第一个参数调用原始方法:

class myclassmethod(object):
    def __init__(self, method):
        self.method = method
    def __get__(self, instance, cls):
        return lambda *args, **kw: self.method(cls, *args, **kw)

在Python控制台上:

>>> class MyClass(object):
...     @myclassmethod
...     def method(cls):
...         print cls
... 
>>> 
>>> m = MyClass()
>>> m.method()
<class '__main__.MyClass'>
>>> 

*编辑 - 更新*

O.P.进一步询问“如果我希望装饰者也接受一个参数,那么初始化的格式是什么?” -

在这种情况下,不仅需要更改__init__ - 接受配置参数的装饰器实际上是在“两个阶段”中调用的 - 第一个是注释参数,并返回一个可调用的 - 第二个call只接受实际装饰的功能。

有几种方法可以做到 - 但我认为最简单的方法是使用一个返回上面类的函数,如:

def myclasmethod(par1, par2, ...):
    class _myclassmethod(object):
        def __init__(self, method):
            self.method = method
        def __get__(self, instance, cls):
            # make use of par1, par2,... variables here at will
            return lambda *args, **kw: self.method(cls, *args, **kw)
    return _myclassmethod

答案 1 :(得分:12)

tar -zxf Python-2.7.2.tgz
vim Python-2.7.2/Objects/funcobject.c

...
589 /* Class method object */
590 
591 /* A class method receives the class as implicit first argument,
592    just like an instance method receives the instance.
593    To declare a class method, use this idiom:
594 
595      class C:
596      def f(cls, arg1, arg2, ...): ...
597      f = classmethod(f)
598 
599    It can be called either on the class (e.g. C.f()) or on an instance
600    (e.g. C().f()); the instance is ignored except for its class.
601    If a class method is called for a derived class, the derived class
602    object is passed as the implied first argument.
603 
604    Class methods are different than C++ or Java static methods.
605    If you want those, see static methods below.
606 */
...