confusion with decorators

Jason Swails jason.swails at gmail.com
Thu Jan 31 17:00:58 CET 2013


On Thu, Jan 31, 2013 at 10:28 AM, Chris Angelico <rosuav at 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...

Thanks!
Jason

-- 
Jason M. Swails
Quantum Theory Project,
University of Florida
Ph.D. Candidate
352-392-4032
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20130131/6022113e/attachment.html>


More information about the Python-list mailing list