<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Decorators and Descriptors</title>
	<atom:link href="http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/</link>
	<description></description>
	<lastBuildDate>Wed, 08 Sep 2010 10:58:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Simon Sapin</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-159737</link>
		<dc:creator>Simon Sapin</dc:creator>
		<pubDate>Sun, 18 Apr 2010 23:33:06 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-159737</guid>
		<description>If the decorated objects are functions (or methods), they have a `__name__` attribute, so you don’t need to pass explicitly the name to the descriptor.  The cached_property class in Armin Ronacher’s Werkzeug uses it:

    class cached_property(object):
        &quot;&quot;&quot;A decorator that converts a function into a lazy property.  The
        function wrapped is called the first time to retrieve the result
        and then that calculated result is used the next time you access
        the value::

            class Foo(object):

                @cached_property
                def foo(self):
                    # calculate something important here
                    return 42

        The class has to have a `__dict__` in order for this property to
        work.
        &quot;&quot;&quot;

        # implementation detail: this property is implemented as non-data
        # descriptor.  non-data descriptors are only invoked if there is
        # no entry with the same name in the instance&#039;s __dict__.
        # this allows us to completely get rid of the access function call
        # overhead.  If one choses to invoke __get__ by hand the property
        # will still work as expected because the lookup logic is replicated
        # in __get__ for manual invocation.

        def __init__(self, func, name=None, doc=None):
            self.__name__ = name or func.__name__
            self.__module__ = func.__module__
            self.__doc__ = doc or func.__doc__
            self.func = func

        def __get__(self, obj, type=None):
            if obj is None:
                return self
            value = obj.__dict__.get(self.__name__, _missing)
            if value is _missing:
                value = self.func(obj)
                obj.__dict__[self.__name__] = value
            return value</description>
		<content:encoded><![CDATA[<p>If the decorated objects are functions (or methods), they have a <code>__name__</code> attribute, so you don’t need to pass explicitly the name to the descriptor.  The cached_property class in Armin Ronacher’s Werkzeug uses it:</p>

<pre><code>class cached_property(object):
    """A decorator that converts a function into a lazy property.  The
    function wrapped is called the first time to retrieve the result
    and then that calculated result is used the next time you access
    the value::

        class Foo(object):

            @cached_property
            def foo(self):
                # calculate something important here
                return 42

    The class has to have a `__dict__` in order for this property to
    work.
    """

    # implementation detail: this property is implemented as non-data
    # descriptor.  non-data descriptors are only invoked if there is
    # no entry with the same name in the instance's __dict__.
    # this allows us to completely get rid of the access function call
    # overhead.  If one choses to invoke __get__ by hand the property
    # will still work as expected because the lookup logic is replicated
    # in __get__ for manual invocation.

    def __init__(self, func, name=None, doc=None):
        self.__name__ = name or func.__name__
        self.__module__ = func.__module__
        self.__doc__ = doc or func.__doc__
        self.func = func

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        value = obj.__dict__.get(self.__name__, _missing)
        if value is _missing:
            value = self.func(obj)
            obj.__dict__[self.__name__] = value
        return value
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris Jones</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-138836</link>
		<dc:creator>Chris Jones</dc:creator>
		<pubDate>Thu, 19 Nov 2009 10:51:13 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-138836</guid>
		<description>Indeed, but any solution is going to be a hack because it&#039;s working around what is (IMO) a bug in Python class-based decorators.

I got around to benchmarking this and, surprisingly, creating a new class on each call is actually *less expensive* than the extra attribute access, even with \_\_slots\_\_ defined.  I&#039;m guessing this has to do with behind-the-scenes MRO stuff going on.  The difference is very slight and probably isn&#039;t a practical consideration, but just throwing that out there.  Here&#039;s the code and results (CPython 2.6 on single-core i386):


    $ python test.py
    30.59: MakeNewClass
    30.48: MakeNewClass_Slots
    33.97: StashObject
    33.69: StashObject_Slots 

    $ cat test.py
    import sys
    import time
    
    class MakeNewClass(object):
        def __init__(self, func):
            self.func = func
        def __call__(self):
            self.func()
        def __get__(self, obj, type):
            return self.__class__(self.func.__get__(obj, type))
    
    class MakeNewClass_Slots(object):
        __slots__ = (&#039;func&#039;,)
        def __init__(self, func):
            self.func = func
        def __call__(self):
            self.func()
        def __get__(self, obj, type):
            return self.__class__(self.func.__get__(obj, type))
    
    class StashObject(object):
        def __init__(self, func):
            self.func = func
        def __call__(self):
            self.func(self.obj)
        def __get__(self, obj, type):
            self.obj = obj
            return self
    
    class StashObject_Slots(object):
        __slots__ = (&#039;func&#039;, &#039;obj&#039;)
        def __init__(self, func):
            self.func = func
        def __call__(self):
            self.func(self.obj)
        def __get__(self, obj, type):
            self.obj = obj
            return self

    class Test(object):
        @MakeNewClass
        def test_a(self):
            pass
        @MakeNewClass_Slots
        def test_b(self):
            pass
        @StashObject
        def test_c(self):
            pass
        @StashObject_Slots
        def test_d(self):
            pass
    
    t = Test()
    for func in t.test_a, t.test_b, t.test_c, t.test_d:
        start = time.time()
        for i in xrange(30000000):
            func()
        print &#039;%.2f: %s&#039; % (time.time() - start, func.__class__.__name__)</description>
		<content:encoded><![CDATA[<p>Indeed, but any solution is going to be a hack because it&#8217;s working around what is (IMO) a bug in Python class-based decorators.</p>

<p>I got around to benchmarking this and, surprisingly, creating a new class on each call is actually <em>less expensive</em> than the extra attribute access, even with &#95;&#95;slots&#95;&#95; defined.  I&#8217;m guessing this has to do with behind-the-scenes MRO stuff going on.  The difference is very slight and probably isn&#8217;t a practical consideration, but just throwing that out there.  Here&#8217;s the code and results (CPython 2.6 on single-core i386):</p>

<pre><code>$ python test.py
30.59: MakeNewClass
30.48: MakeNewClass_Slots
33.97: StashObject
33.69: StashObject_Slots 

$ cat test.py
import sys
import time

class MakeNewClass(object):
    def __init__(self, func):
        self.func = func
    def __call__(self):
        self.func()
    def __get__(self, obj, type):
        return self.__class__(self.func.__get__(obj, type))

class MakeNewClass_Slots(object):
    __slots__ = ('func',)
    def __init__(self, func):
        self.func = func
    def __call__(self):
        self.func()
    def __get__(self, obj, type):
        return self.__class__(self.func.__get__(obj, type))

class StashObject(object):
    def __init__(self, func):
        self.func = func
    def __call__(self):
        self.func(self.obj)
    def __get__(self, obj, type):
        self.obj = obj
        return self

class StashObject_Slots(object):
    __slots__ = ('func', 'obj')
    def __init__(self, func):
        self.func = func
    def __call__(self):
        self.func(self.obj)
    def __get__(self, obj, type):
        self.obj = obj
        return self

class Test(object):
    @MakeNewClass
    def test_a(self):
        pass
    @MakeNewClass_Slots
    def test_b(self):
        pass
    @StashObject
    def test_c(self):
        pass
    @StashObject_Slots
    def test_d(self):
        pass

t = Test()
for func in t.test_a, t.test_b, t.test_c, t.test_d:
    start = time.time()
    for i in xrange(30000000):
        func()
    print '%.2f: %s' % (time.time() - start, func.__class__.__name__)
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mathieu</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-138730</link>
		<dc:creator>Mathieu</dc:creator>
		<pubDate>Wed, 18 Nov 2009 06:01:18 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-138730</guid>
		<description>Your solution is a bit of a hack but I like it better. The problem with the __get __ method originally suggested is that it does &quot;return self.__class __(new_func)&quot;. This will cause a new instance of the class to be created again and again...</description>
		<content:encoded><![CDATA[<p>Your solution is a bit of a hack but I like it better. The problem with the __get __ method originally suggested is that it does &#8220;return self.__class __(new_func)&#8221;. This will cause a new instance of the class to be created again and again&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ale</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124388</link>
		<dc:creator>Ale</dc:creator>
		<pubDate>Tue, 18 Aug 2009 10:08:57 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124388</guid>
		<description>Using the function you suggest will work for method decorating but not for function decorating.  That was the point of using a descriptor and the reason to go with a class; it can handle both cases</description>
		<content:encoded><![CDATA[<p>Using the function you suggest will work for method decorating but not for function decorating.  That was the point of using a descriptor and the reason to go with a class; it can handle both cases</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: chris jones</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124274</link>
		<dc:creator>chris jones</dc:creator>
		<pubDate>Mon, 17 Aug 2009 16:36:40 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124274</guid>
		<description>Yeah, I guess my point is you could just use a function instead of a class in the first place and not bother with any of this.  This problem comes up every so often and it seems like people forget you can do that, because they get so invested in solving the bound/unbound method problem.  When you think about it, adding \_\_call\_\_ to the class instance is just pretending it&#039;s a function.  Here&#039;s how I would write the original decorator:

    def wsgiapp(func):
        def inner(self, environ, start_response):
            resp = func(self, Request(environ))
            return resp(environ, start_response)
        return inner

Does the same thing, no magic.

I suppose class-based deco&#039;s are useful if your decorator needs to save state between calls or share it with other decorated functions, but there are other ways to do that, such as having the inner function close over a dict. IMO, decorators are a functional idiom and trying to force them to work as an object by introducing all this magic might not be the best practical solution, although it&#039;s a fun exercise in python internal hacking.</description>
		<content:encoded><![CDATA[<p>Yeah, I guess my point is you could just use a function instead of a class in the first place and not bother with any of this.  This problem comes up every so often and it seems like people forget you can do that, because they get so invested in solving the bound/unbound method problem.  When you think about it, adding &#95;&#95;call&#95;&#95; to the class instance is just pretending it&#8217;s a function.  Here&#8217;s how I would write the original decorator:</p>

<pre><code>def wsgiapp(func):
    def inner(self, environ, start_response):
        resp = func(self, Request(environ))
        return resp(environ, start_response)
    return inner
</code></pre>

<p>Does the same thing, no magic.</p>

<p>I suppose class-based deco&#8217;s are useful if your decorator needs to save state between calls or share it with other decorated functions, but there are other ways to do that, such as having the inner function close over a dict. IMO, decorators are a functional idiom and trying to force them to work as an object by introducing all this magic might not be the best practical solution, although it&#8217;s a fun exercise in python internal hacking.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ale</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124137</link>
		<dc:creator>Ale</dc:creator>
		<pubDate>Sun, 16 Aug 2009 09:59:36 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124137</guid>
		<description>Chris says

    This will re-bind the inner function to the obj instance and then 
    remove the __get__ method, however you just monkey-patched your 
    decorator — meaning you can only decorate one function. Not very 
    useful, obviously

From my point of view, very useful, since that means that if you transform it from a class to a function that returns a class, you are set.

ie

    def deco():
        class inner(object):

            def __init__(self, func):
                self.func = func

            def __call__(self, arg):
                return self.func(arg)

            def __get__(self, obj, type=None):
                self.func = self.func.__get__(obj, type)
                del self.__class__.__get__
                return self
        return inner


Seems to work well, even though it&#039;s an uglyish syntax.

Using a class decorator makes it a little more succinct:

    def classIsADescriptorDecorator(klass):
        def __init__(self, func):
            self.func = func

        def __get__(self, obj, type=None):
            self.func = self.func.__get__(obj, type)
            del self.__class__.__get__
            return self

        klass.__init__ = __init__
        klass.__get__ = __get__

        return klass

    def deco():
        @classIsADescriptorDecorator
        class inner(object):
            def __call__(self, arg):
                return self.func(arg)


And further, increasing the magic quotient by creating a new class on the fly, we can make it shorter:

    def decorate(klass):
        newType = type(&#039;newType&#039;, klass.__class__.__bases__, dict(klass.__dict__))
        return classIsADescriptorDecorator(newType)


which can be used as following:

    class Printer(object):
        def __call__(self, arg):
             print arg
             return self.func(arg)


    @decorate(Printer)
    def notAPrinter(arg):
         print &quot;I&#039;m not a printer: %s&quot; % arg


This last one looks fragile.</description>
		<content:encoded><![CDATA[<p>Chris says</p>

<pre><code>This will re-bind the inner function to the obj instance and then 
remove the __get__ method, however you just monkey-patched your 
decorator — meaning you can only decorate one function. Not very 
useful, obviously
</code></pre>

<p>From my point of view, very useful, since that means that if you transform it from a class to a function that returns a class, you are set.</p>

<p>ie</p>

<pre><code>def deco():
    class inner(object):

        def __init__(self, func):
            self.func = func

        def __call__(self, arg):
            return self.func(arg)

        def __get__(self, obj, type=None):
            self.func = self.func.__get__(obj, type)
            del self.__class__.__get__
            return self
    return inner
</code></pre>

<p>Seems to work well, even though it&#8217;s an uglyish syntax.</p>

<p>Using a class decorator makes it a little more succinct:</p>

<pre><code>def classIsADescriptorDecorator(klass):
    def __init__(self, func):
        self.func = func

    def __get__(self, obj, type=None):
        self.func = self.func.__get__(obj, type)
        del self.__class__.__get__
        return self

    klass.__init__ = __init__
    klass.__get__ = __get__

    return klass

def deco():
    @classIsADescriptorDecorator
    class inner(object):
        def __call__(self, arg):
            return self.func(arg)
</code></pre>

<p>And further, increasing the magic quotient by creating a new class on the fly, we can make it shorter:</p>

<pre><code>def decorate(klass):
    newType = type('newType', klass.__class__.__bases__, dict(klass.__dict__))
    return classIsADescriptorDecorator(newType)
</code></pre>

<p>which can be used as following:</p>

<pre><code>class Printer(object):
    def __call__(self, arg):
         print arg
         return self.func(arg)


@decorate(Printer)
def notAPrinter(arg):
     print "I'm not a printer: %s" % arg
</code></pre>

<p>This last one looks fragile.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ian Bicking</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124094</link>
		<dc:creator>Ian Bicking</dc:creator>
		<pubDate>Sat, 15 Aug 2009 20:14:03 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124094</guid>
		<description>You can kind of do this, but it&#039;s difficult.  Your descriptor would have to know the attribute it was bound to.  So you might do:

    class cache_descriptor(object):
        def __init__(self, attr, descriptor):
            self.attr = attr
            self.descriptor = descriptor
        def __get__(self, obj, type=None):
            result = self.descriptor.__get__(obj, type)
            if obj is not None:
                obj.__dict__[self.attr] = result
            return result
        def __set__(self, obj, value):
            self.descriptor.__set__(obj, value)
        def __delete__(self, obj):
            self.descriptor.__delete__(obj)

Then you could do something like:

    class MyThingy(object):
        @whatever
        def __call__(self, ...): ...
        __call__ = cache_descriptor(&#039;__call__&#039;, __call__)

Or maybe separately:

    def cache_descriptors(cls, *methods):
        for method in methods:
            setattr(cls, method, cache_descriptor(method, getattr(cls, method)))

    class MyThingy(object): ...
    cache_descriptors(MyThingy, &#039;__call__&#039;, &#039;something_else&#039;, ...)

I don&#039;t cache these values in WebOb, but I do use a pattern of nested descriptors (`webob.converter`).</description>
		<content:encoded><![CDATA[<p>You can kind of do this, but it&#8217;s difficult.  Your descriptor would have to know the attribute it was bound to.  So you might do:</p>

<pre><code>class cache_descriptor(object):
    def __init__(self, attr, descriptor):
        self.attr = attr
        self.descriptor = descriptor
    def __get__(self, obj, type=None):
        result = self.descriptor.__get__(obj, type)
        if obj is not None:
            obj.__dict__[self.attr] = result
        return result
    def __set__(self, obj, value):
        self.descriptor.__set__(obj, value)
    def __delete__(self, obj):
        self.descriptor.__delete__(obj)
</code></pre>

<p>Then you could do something like:</p>

<pre><code>class MyThingy(object):
    @whatever
    def __call__(self, ...): ...
    __call__ = cache_descriptor('__call__', __call__)
</code></pre>

<p>Or maybe separately:</p>

<pre><code>def cache_descriptors(cls, *methods):
    for method in methods:
        setattr(cls, method, cache_descriptor(method, getattr(cls, method)))

class MyThingy(object): ...
cache_descriptors(MyThingy, '__call__', 'something_else', ...)
</code></pre>

<p>I don&#8217;t cache these values in WebOb, but I do use a pattern of nested descriptors (<code>webob.converter</code>).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: chris jones</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124087</link>
		<dc:creator>chris jones</dc:creator>
		<pubDate>Sat, 15 Aug 2009 19:27:06 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124087</guid>
		<description>Hmm.. thought about this some more.  You  could always just use \_\_get\_\_ to stash the self object, and pass it explicitly in the wrapped function.  I&#039;m not sure if this performs better or not, but it&#039;s at least easier to understand:

    class deco(object):
    
        def __init__(self, func):
            self.func = func
            self.obj = None
    
        def __call__(self, arg):
            return self.func(self.obj, arg)
    
        def __get__(self, obj, type=None):
            self.obj = obj
            return self</description>
		<content:encoded><![CDATA[<p>Hmm.. thought about this some more.  You  could always just use &#95;&#95;get&#95;&#95; to stash the self object, and pass it explicitly in the wrapped function.  I&#8217;m not sure if this performs better or not, but it&#8217;s at least easier to understand:</p>

<pre><code>class deco(object):

    def __init__(self, func):
        self.func = func
        self.obj = None

    def __call__(self, arg):
        return self.func(self.obj, arg)

    def __get__(self, obj, type=None):
        self.obj = obj
        return self
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: chris jones</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-124084</link>
		<dc:creator>chris jones</dc:creator>
		<pubDate>Sat, 15 Aug 2009 19:17:46 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-124084</guid>
		<description>Ale, I&#039;ve tried everything to accomplish that and have not succeeded due to \_\_get\_\_ living on the class and not the instance.   For example, you could do this:

    class deco(object):
    
        def __init__(self, func):
            self.func = func
    
        def __call__(self, arg):
            return self.func(arg)
    
        def __get__(self, obj, type=None):
            self.func = self.func.__get__(obj, type)
            del deco.__get__
            return self

This will re-bind the inner function to the obj instance and then remove the \_\_get\_\_ method, however you just monkey-patched your decorator -- meaning *you can only decorate one function*.  Not very useful, obviously.  The reason this works is the reason you have to instantiate on every call: Descriptors operate on the class level.

To be honest, I think it makes more sense to decorate instance methods with *functional* rather than class-based decorators.  For one, it does not have the problem of the unbound method failing to pass implicit self.  Second of all, decorating is inherently a functional operation.  Wrapping the whole thing in a class with \_\_call\_\_ defined is just ugly and confusing IMO.  Then on top of that,  overriding \_\_get\_\_ to re-bind the function is a hack; one that could have significant performance implications if called in a tight loop.</description>
		<content:encoded><![CDATA[<p>Ale, I&#8217;ve tried everything to accomplish that and have not succeeded due to &#95;&#95;get&#95;&#95; living on the class and not the instance.   For example, you could do this:</p>

<pre><code>class deco(object):

    def __init__(self, func):
        self.func = func

    def __call__(self, arg):
        return self.func(arg)

    def __get__(self, obj, type=None):
        self.func = self.func.__get__(obj, type)
        del deco.__get__
        return self
</code></pre>

<p>This will re-bind the inner function to the obj instance and then remove the &#95;&#95;get&#95;&#95; method, however you just monkey-patched your decorator &#8212; meaning <em>you can only decorate one function</em>.  Not very useful, obviously.  The reason this works is the reason you have to instantiate on every call: Descriptors operate on the class level.</p>

<p>To be honest, I think it makes more sense to decorate instance methods with <em>functional</em> rather than class-based decorators.  For one, it does not have the problem of the unbound method failing to pass implicit self.  Second of all, decorating is inherently a functional operation.  Wrapping the whole thing in a class with &#95;&#95;call&#95;&#95; defined is just ugly and confusing IMO.  Then on top of that,  overriding &#95;&#95;get&#95;&#95; to re-bind the function is a hack; one that could have significant performance implications if called in a tight loop.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Profjim</title>
		<link>http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/comment-page-1/#comment-104706</link>
		<dc:creator>Profjim</dc:creator>
		<pubDate>Tue, 05 May 2009 00:31:14 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/#comment-104706</guid>
		<description>@Schuyler: here&#039;s why I think your use case for @deco is working.

You originally tried:

class Foo:
	def bar(self,x):
	return x*3

class Baz:
	#what some TG decorators do:
	foo = Foo()
	foo.bar.expose = True

which gave you an AttributeError: &#039;instancemethod&#039; object has no attribute &#039;expose&#039;.

What&#039;s going on here is that foo.bar is a bound method (isinstance(foo.bar, types.MethodType)) and neither they (nor unbound methods like Foo.bar)
have __dict__&#039;s. Hence you can&#039;t assign new attributes to them.

When you use the @deco technique instead:

class Foo:
	@deco
	def bar(self,x):
		return x*3

class Baz:
	foo = Foo()
	foo.bar.expose = True

now foo.bar is no longer a method. Instead, it&#039;s an attribute of foo which has a deco object as its value. This object does have a __dict__ and can be assigned arbitrary new attributes, like expose.</description>
		<content:encoded><![CDATA[<p>@Schuyler: here&#8217;s why I think your use case for @deco is working.</p>

<p>You originally tried:</p>

<p>class Foo:
    def bar(self,x):
    return x*3</p>

<p>class Baz:
    #what some TG decorators do:
    foo = Foo()
    foo.bar.expose = True</p>

<p>which gave you an AttributeError: &#8216;instancemethod&#8217; object has no attribute &#8216;expose&#8217;.</p>

<p>What&#8217;s going on here is that foo.bar is a bound method (isinstance(foo.bar, types.MethodType)) and neither they (nor unbound methods like Foo.bar)
have <strong>dict</strong>&#8217;s. Hence you can&#8217;t assign new attributes to them.</p>

<p>When you use the @deco technique instead:</p>

<p>class Foo:
    @deco
    def bar(self,x):
        return x*3</p>

<p>class Baz:
    foo = Foo()
    foo.bar.expose = True</p>

<p>now foo.bar is no longer a method. Instead, it&#8217;s an attribute of foo which has a deco object as its value. This object does have a <strong>dict</strong> and can be assigned arbitrary new attributes, like expose.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.405 seconds -->
