Местоположение @classmethod - PullRequest
       15

Местоположение @classmethod

8 голосов
/ 12 февраля 2012

Где находится исходный код метода класса декоратора, расположенный в исходном коде Python.В частности, у меня возникают проблемы с поиском точного файла, который определен в версии 2.7.2

Ответы [ 2 ]

18 голосов
/ 12 февраля 2012

Я не отвечаю на то, что вы спросили, - но ниже показано, что может быть декоратором, эквивалентным classmethod, написанному на Pure Python - поскольку исходный код находится в C, внутри Python-2.7.2/Objects/funcobject.c как Мишна вставляет свой ответ.

Итак, идея методов класса состоит в том, чтобы использовать механизм «дескриптора», как описано в Модель данных Python , - и сделать так, чтобы метод __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'>
>>> 

* РЕДАКТИРОВАТЬ - Обновление *

О.П. также спросил: «Если бы я хотел, чтобы декоратор также принял параметр, какой формат был бы правильным для init?» -

В этом случае необходимо изменить не только __init__ - декоратор, принимающий параметры конфигурации, на самом деле вызывается в "два этапа" - первый аннотирует параметры и возвращает вызываемый - второй вызов принимает только та функция, которая на самом деле будет оформлена.

Есть несколько способов сделать это - но я думаю, что самым простым является иметь функцию, которая возвращает класс выше, как в:

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
12 голосов
/ 12 февраля 2012
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 */
...
...