How does this Python decorator work?

回眸只為那壹抹淺笑 提交于 2019-12-09 07:00:33

问题


I was looking at some lazy loading property decorators in Python and happened across this example (http://code.activestate.com/recipes/363602-lazy-property-evaluation/):

class Lazy(object):
    def __init__(self, calculate_function):
        self._calculate = calculate_function

    def __get__(self, obj, _=None):
        if obj is None:
            return self
        value = self._calculate(obj)
        setattr(obj, self._calculate.func_name, value)
        return value

# Sample use:

class SomeClass(object):

    @Lazy
    def someprop(self):
        print 'Actually calculating value'
        return 13

o = SomeClass()
o.someprop
o.someprop

My question is, how does this work? My understanding of decorators is that they must be callable (so either a function or a call that implements __call__), but Lazy here clearly is not and if I try Lazy(someFunc)() it raises an exception as expected. What am I missing?


回答1:


When an attribute named someprop is accessed on instance o of class SomeClass, if SomeClass contains a descriptor named o, then that descriptor's class's __get__ method is used. For more on descriptors, see this guide. Don't let the fact that Lazy is here used, syntactically, as a decorator, blind you to the fact that its instances are descriptors, because Lazy itself has a __get__ method.

The decorator syntax

    @Lazy
    def someprop(self):
       ...

is no more, and no less, than syntax sugar for:

    def someprop(self):
       ...
    someprop = Lazy(someprop)

The constraints on Lazy are no different when it's used with decorator syntax or directly: it must accept someprop (a function) as its argument -- no constraints whatsoever on what it returns. Here, Lazy is a class so it returns an instance of itself, and has a __get__ special method so that instance is a descriptor (so said method gets called when the someprop attribute is accessed on the instance o of class SomeClass) -- that's all there is to it, no more, and no less.



来源:https://stackoverflow.com/questions/3103463/how-does-this-python-decorator-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!