Descriptor / decorator attachments in python

I find it difficult to understand what happens when I try to insert descriptors / decorators. I am using python 2.7.

For example, suppose the following simplified versions propertyand classmethod:

class MyProperty(object):
    def __init__(self, fget):
        self.fget = fget
    def __get__(self, obj, objtype=None):
        print 'IN MyProperty.__get__'
        return self.fget(obj)

class MyClassMethod(object):
    def __init__(self, f):
       self.f = f
    def __get__(self, obj, objtype=None):
        print 'IN MyClassMethod.__get__'
        def f(*args, **kwargs):
            return self.f(objtype, *args, **kwargs)
        return f

Attempt to invest them:

class A(object):
    # doesn't work:
    @MyProperty
    @MyClassMethod
    def klsproperty(cls):
        return 555
    # works:
    @MyProperty
    def prop(self):
        return 111
    # works:
    @MyClassMethod
    def klsmethod(cls, x):
        return x**2

% print A.klsproperty
IN MyProperty.__get__
...
TypeError: 'MyClassMethod' object is not callable

The __get__internal descriptor method is MyClassMethodnot called. If you don’t understand why, I tried using (no-op descriptor):

class NoopDescriptor(object):
    def __init__(self, f):
       self.f = f
    def __get__(self, obj, objtype=None):
        print 'IN NoopDescriptor.__get__'
        return self.f.__get__(obj, objtype=objtype)

Attempt to use the descriptor / decorator no-op when nesting:

class B(object):
    # works:
    @NoopDescriptor
    @MyProperty
    def prop1(self):
        return 888
    # doesn't work:
    @MyProperty
    @NoopDescriptor
    def prop2(self):
        return 999

% print B().prop1
IN NoopDescriptor.__get__
IN MyProperty.__get__
888
% print B().prop2
IN MyProperty.__get__
...
TypeError: 'NoopDescriptor' object is not callable

I do not understand why it B().prop1works, but B().prop2does not work.

Questions:

  • What am I doing wrong? Why am I getting an error object is not callable?
  • Which is the right way? such that the best way to determine MyClassPropertywhen reusing MyClassMethodand MyProperty(or classmethodand property)
+5
3

, MyProperty :

class MyProperty(object):
    def __init__(self, fget):
        self.fget = fget
    def __get__(self, obj, objtype=None):
        print('IN MyProperty.__get__')
        try:
            return self.fget.__get__(obj, objtype)()
        except AttributeError: # self.fget has no __get__ method
            return self.fget(obj)

:

class A(object):
    @MyProperty
    @MyClassMethod
    def klsproperty(cls):
        return 555

print(A.klsproperty)

:

IN MyProperty.__get__
IN MyClassMethod.__get__
555
+3

, , , . . :

@MyProperty
def prop(self):
    ...

:

def prop(self):
    ...
prop = MyProperty(prop)

MyProperty , A.prop A.prop.__get__(), __get__, ( /) .

:

@MyProperty
@MyClassMethod
def prop(self):
    ...

:

def prop(self):
    ...
prop = MyClassMethod(prop)   # prop is now instance of MyClassMethod
prop = MyProperty(prop)      # prop is now instance of MyProperty
                             # (with fget == MyClassMethod instance)

, , A.prop A.prop.__get__() ( MyProperty), MyClassMethod (, fget),.

MyClassMethod __call__, MyClassMethod is not callable.


: . A.prop , A().prop ( , , ).

+5

Graham Dumpleton, blog.

, , , , /, , " " ( __get__()).

0

All Articles