Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #38004

Re: confusion with decorators

Path csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.straub-nv.de!newsreader4.netcologne.de!news.netcologne.de!feeder1.cambriumusenet.nl!82.197.223.103.MISMATCH!feeder3.cambriumusenet.nl!feed.tweaknews.nl!194.109.133.86.MISMATCH!newsfeed.xs4all.nl!newsfeed3.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail
Return-Path <jason.swails@gmail.com>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.000
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; '(at': 0.03; '"""': 0.05; 'attribute': 0.05; 'run-time': 0.05; '*args,': 0.07; 'bug.': 0.07; 'calls.': 0.07; 'decorator': 0.07; 'function,': 0.07; 'try:': 0.07; 'urllib2': 0.07; 'python': 0.09; '**kwargs)': 0.09; '**kwargs):': 0.09; 'called.': 0.09; 'naturally': 0.09; 'cc:addr :python-list': 0.10; 'def': 0.10; '&gt;&gt;': 0.16; '(via': 0.16; 'a(object):': 0.16; 'duplicating': 0.16; 'httperror': 0.16; 'httperror,': 0.16; 'indexerror:': 0.16; 'instantiate': 0.16; 'lend': 0.16; 'scope.': 0.16; "time'": 0.16; 'wrappers': 0.16; '\xa0def': 0.16; 'string': 0.17; 'wrote:': 0.17; 'example.': 0.17; 'implementing': 0.17; 'thu,': 0.17; 'jan': 0.18; 'appropriate': 0.20; 'code.': 0.20; 'email addr:gmail.com&gt;': 0.20; 'trying': 0.21; 'import': 0.21; 'do.': 0.21; '31,': 0.22; 'decorators': 0.22; '\xa0if': 0.22; 'defined': 0.22; 'skip:_ 20': 0.22; 'work,': 0.22; "i'd": 0.22; 'cc:2**0': 0.23; '&gt;': 0.23; '(i.e.,': 0.23; 'seems': 0.23; 'raise': 0.24; 'cc:no real name:2**0': 0.24; 'least': 0.25; 'cc:addr:python.org': 0.25; 'header:In-Reply-To:1': 0.25; 'expand': 0.26; 'am,': 0.27; 'right.': 0.27; 'message- id:@mail.gmail.com': 0.27; 'chris': 0.28; 'closer': 0.29; 'declared': 0.29; 'overhead': 0.29; 'wrap': 0.29; 'objects': 0.29; '8bit%:5': 0.29; 'skip:_ 10': 0.29; 'skip:& 10': 0.29; 'class': 0.29; "i'm": 0.29; 'related': 0.30; 'function': 0.30; 'code': 0.31; 'could': 0.32; 'surely': 0.33; 'themselves': 0.33; 'received:google.com': 0.34; 'list': 0.35; 'adds': 0.35; 'jason': 0.35; 'except': 0.36; 'but': 0.36; 'child': 0.36; 'subject:with': 0.36; 'should': 0.36; 'skip:p 20': 0.36; 'possible': 0.37; 'bad': 0.37; 'level': 0.37; 'why': 0.37; 'passed': 0.37; 'rather': 0.37; 'subject:: ': 0.38; 'sure': 0.38; 'instead': 0.39; 'think': 0.40; 'skip:u 10': 0.60; 'more': 0.63; 'behavior': 0.64; 'grab': 0.64; 'here': 0.65; 'risk': 0.66; 'acts': 0.71; '2013': 0.84; "available.'": 0.84; 'basically,': 0.84; 'decorate': 0.84; 'locally': 0.84; '\xa0basically,': 0.84; 'impressions': 0.91; 'to:none': 0.93
DKIM-Signature v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:cc:content-type; bh=LWNYp5pg98nN6FqPGlUCXHFrU4LwEx9k5rt5fVUt7os=; b=aBdpwbWzw/TdyKmXY8Qmo6c5ybf7S8D/3KPS1JPToDq8mAO+auI0HASi5tbObMDEvP 9E3ouA+J6TTjS2mJuas+nd1TKqBpkTFROOa+o8YTKTeYgYiM2q+T8ZixV02Go8WpB4nJ qSgZ5dQKBJM6uexem2bjovvc0jCv7PBoRqq367/BqYCrUnXrib/knohoxy88Du3Hb36u A7UvjCBliYh76gGtru8gl+10qxKfb02rgHBXC52Y5CTYCjeMwPzzNNFpiKhzHu2Y7jri dF6HlOJbTw/+rrrG0CgeTSjHDupwyg5WaRtIcVlTmrUzSnQFvZL23GLd/FzMKn0ykofc 5CMA==
MIME-Version 1.0
X-Received by 10.50.158.168 with SMTP id wv8mr1863704igb.80.1359654793377; Thu, 31 Jan 2013 09:53:13 -0800 (PST)
In-Reply-To <CAEk9e3rnxA0buftMkyN_4azb+jphtOP1ecHkDqBi811V7XBBhg@mail.gmail.com>
References <mailman.1239.1359592452.2939.python-list@python.org> <510a053a$0$11104$c3e8da3@news.astraweb.com> <CAEk9e3rbH8Jt9pL4zS=g5uEJZiRiPKDP=cMzaC7D-c2dnMBsMw@mail.gmail.com> <CAPTjJmqLQ-L=Z_e4es2=34DMCLK4ZcJpmia4v2udipTTsQeCvw@mail.gmail.com> <CAEk9e3rnxA0buftMkyN_4azb+jphtOP1ecHkDqBi811V7XBBhg@mail.gmail.com>
Date Thu, 31 Jan 2013 12:53:13 -0500
Subject Re: confusion with decorators
From Jason Swails <jason.swails@gmail.com>
Cc python-list@python.org
Content-Type multipart/alternative; boundary=14dae9340c49f9f60d04d4994ceb
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.15
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <http://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <http://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Newsgroups comp.lang.python
Message-ID <mailman.1252.1359654802.2939.python-list@python.org> (permalink)
Lines 224
NNTP-Posting-Host 2001:888:2000:d::a6
X-Trace 1359654802 news.xs4all.nl 6906 [2001:888:2000:d::a6]:34424
X-Complaints-To abuse@xs4all.nl
Xref csiph.com comp.lang.python:38004

Show key headers only | View raw


[Multipart message — attachments visible in raw view] - view raw

On Thu, Jan 31, 2013 at 11:00 AM, Jason Swails <jason.swails@gmail.com>wrote:

>
>
> On Thu, Jan 31, 2013 at 10:28 AM, Chris Angelico <rosuav@gmail.com> wrote:
>
>>
>> >> Well, that surely isn't going to work, because it always decorates the
>> >> same function, the global "fcn".
>> >
>> >
>> > I don't think this is right.  fcn is a passed function (at least if it
>> acts
>> > as a decorator) that is declared locally in the _protector_decorator
>> scope.
>> > Since newfcn is bound in the same scope and fcn is not defined inside
>> > newfcn, I'm pretty sure that newfcn will just grab the fcn passed into
>> the
>> > decorator.
>>
>> Yet it adds a level of indirection that achieves nothing. Why not simply:
>> def _protector_decorator(fcn):
>>   return fcn
>>
>> ? I'm not understanding the purpose here.
>>
>
> Bad example.  A better (longer) one that is closer to my true use-case:
>
>
> from somewhere.exceptions import MyTypeError
> from somewhere.different import AuthorClass, RemoteAuthorClass
> from urllib2 import HTTPError
>
> class A(object):
>
>    authorclass = AuthorClass
>
>    def __init__(self, obj_list):
>       """
>       Instantiate a list of obj_list objects that may have an "author"
>       attribute
>       """
>       self.things = []
>       for o in obj_list:
>          if not isinstance(o, self.authorclass):
>             raise MyTypeError('Bad type given to constructor')
>          self.things.append(o)
>
>    def _protector(fcn):
>       def newfcn(self, *args, **kwargs):
>          try:
>             return fcn(self, *args, **kwargs) # returns a string
>          except AttributeError:
>             return 'Attribute not available.'
>          except IndexError:
>             return 'Not that many AuthorClasses loaded'
>
>       return newfcn
>
>    @_protector
>    def author(self, idx):
>       return self.things[idx].author
>
>    @_protector
>    def description(self, idx):
>       return self.things[idx].description
>
>    @_protector
>    def hobbies(self, idx):
>       return self.things[idx].hobbies
>
> class B(A):
>
>    authorclass = RemoteAuthorClass
>
>    def _protector(fcn):
>       def newfcn(self, *args, **kwargs):
>          try:
>             return fcn(self, *args, **kwargs)
>          except AttributeError:
>             return 'Attribute not available'
>          except IndexError:
>             return 'Not that many RemoteAuthorClasses loaded'
>          except HTTPError:
>             return 'Could not connect'
>       return fcn
>
> Basically, while RemoteAuthorClass and AuthorClass are related (via
> inheritance), the RemoteAuthorClass has the potential for HTTPError's now.
>  I could just expand the A class decorator to catch the HTTPError, but
> since that should not be possible in AuthorClass, I'd rather not risk
> masking a bug.  I'm under no impressions that the above code will decorate
> A-inherited functions with the B-decorator (I know it won't), but that's
> the effect I'm trying to achieve...
>

The approach I'm switching to here is to make the decorators wrappers
instead that are passed the functions that need to be called.  Basically,
wrap at run-time rather than 'compile time' (i.e., when the Python code is
'compiled' into class definitions).  That way each child of the main class
can simply change the wrapping behavior by implementing the wrapping
functions instead of duplicating all of the code.  And since this part of
the code is not performance-intensive, I don't care about the overhead of
extra function calls.

It seems to me to be the more appropriate course of action here, since
decorators don't seem to naturally lend themselves to what I'm trying to do.

--Jason

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

confusion with decorators Jason Swails <jason.swails@gmail.com> - 2013-01-30 19:34 -0500
  Re: confusion with decorators Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-01-31 05:46 +0000
    Re: confusion with decorators Jason Swails <jason.swails@gmail.com> - 2013-01-31 08:25 -0500
      Re: confusion with decorators Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-01 10:16 +1100
        Re: confusion with decorators Jason Swails <jason.swails@gmail.com> - 2013-01-31 22:13 -0500
    Re: confusion with decorators Chris Angelico <rosuav@gmail.com> - 2013-02-01 02:28 +1100
    Re: confusion with decorators Jason Swails <jason.swails@gmail.com> - 2013-01-31 11:00 -0500
    Re: confusion with decorators Jason Swails <jason.swails@gmail.com> - 2013-01-31 12:53 -0500
    Re: confusion with decorators Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-02-01 08:31 +1100
  Re: confusion with decorators 88888 Dihedral <dihedral88888@googlemail.com> - 2013-02-01 03:26 -0800
  Re: confusion with decorators 88888 Dihedral <dihedral88888@googlemail.com> - 2013-02-01 03:26 -0800

csiph-web