Search code examples
pythondecoratorpython-2.7

Location of @classmethod


Where is the source code for the decorator classmethod located in the python source code. Specifically I am having trouble finding the exact file it's defined in version 2.7.2


Solution

  • I am not answering what you asked - but the code below shows what could be a decorator equivalent to classmethod, written in Pure Python - since the one in the source code is in C, inside Python source code as Mishna puts in his answer (link updated for cPython development branch on GitHub).

    So, the idea of class methods is to use the "descriptor" mechanism, as described in Python's data model - and make it so that the __get__ method does return a function object that when called, will call the original method with the first argument pre-filled:

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

    And on Python console:

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

    *** EDIT - Update ***

    The O.P. further asked "If I wanted the decorator to also accept a parameter what would be the proper format for init? " -

    In that case it is not only __init__ which has to be changed - a decorator that accepts configuration parameters is actually called in "two stages" - the first one annotate the parameters, and returns a callable - the second call accepts only the function which will actually be decorated.

    There are a few ways to do it - but I think the most straightforward is to have a function that returns the class above, like in:

    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