Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 858
user1200501 Avatar asked Feb 12 '12 09:02

user1200501


2 Answers

I am not answering what you asked - but 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-2.7.2/Objects/funcobject.c as Mishna puts in his answer.

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
like image 137
jsbueno Avatar answered Nov 09 '22 22:11

jsbueno


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 */
...
like image 30
Misha Akovantsev Avatar answered Nov 10 '22 00:11

Misha Akovantsev