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


Groups > comp.lang.python > #8585

Re: Using decorators with argument in Python

Date 2011-06-29 14:29 -0700
From Ethan Furman <ethan@stoneleaf.us>
Subject Re: Using decorators with argument in Python
References <d35e1e82-410b-471b-a3c7-379c1822adb0@m22g2000yqh.googlegroups.com> <4e0a0a8b$1@dnews.tpgi.com.au> <4E0B5F7C.7030802@codicesoftware.com> <4E0B7D6A.1080404@stoneleaf.us> <BANLkTimW4=Gdvfh4d5sD-Phzo8qJUuXbrw@mail.gmail.com>
Newsgroups comp.lang.python
Message-ID <mailman.511.1309382125.1164.python-list@python.org> (permalink)

Show all headers | View raw


Ian Kelly wrote:
> On Wed, Jun 29, 2011 at 1:30 PM, Ethan Furman <ethan@stoneleaf.us> wrote:
>> How about just having one bit of code that works either way?
> 
> How would you adapt that code if you wanted to be able to decorate a
> function that takes arguments?

8<----------------------------------------------------------------
class enclose(object):
     func = None
     def __init__(self, char='#'):
         self.char = char
         if callable(char):  # was a function passed in directly?
             self.char = '#' # use default char
             self.func = char
     def __call__(self, func=None, *args, **kwargs):
         if self.func is None:
             self.func = func
             return self
         if func is not None:
             args = (func, ) + args
         return self._call(*args, **kwargs)
     def _call(self, *args, **kwargs):
         print("\n" + self.char * 50)
         self.func(*args, **kwargs)
         print(self.char * 50 + '\n')
if __name__ == '__main__':
     @enclose
     def test1():
         print('Spam!')
     @enclose('-')
     def test2():
         print('Eggs!')
     @enclose
     def test3(string):
         print(string)
     @enclose('^')
     def test4(string):
         print(string)
     test1()
     test2()
     test3('Python')
     test4('Rules!  ;)')
8<----------------------------------------------------------------

> This also won't work if the argument to the decorator is itself a
> callable, such as in the OP's example.

Indeed.  In that case you need two keywords to __init__, and the 
discipline to always use the keyword syntax at least for the optional 
function paramater.  On the bright side, if one forgets, it blows up 
pretty quickly.

Whether it's worth the extra effort depends on the programmer's tastes, 
of course.

8<----------------------------------------------------------------
class enclose(object):
     func = None
     pre_func = None
     def __init__(self, dec_func=None, opt_func=None):
         if opt_func is None:
             if dec_func is not None: # was written without ()'s
                 self.func = dec_func
         else:
             self.pre_func = opt_func
     def __call__(self, func=None, *args, **kwargs):
         if self.func is None:
             self.func = func
             return self
         if func is not None:
             args = (func, ) + args
         if self.pre_func is not None:
             self.pre_func()
         return self._call(*args, **kwargs)
     def _call(self, *args, **kwargs):
         print("\n" + '~' * 50)
         self.func(*args, **kwargs)
         print('~' * 50 + '\n')

if __name__ == '__main__':
     def some_func():
         print('some func here')
     @enclose
     def test1():
         print('Spam!')
     @enclose(opt_func=some_func)
     def test2():
         print('Eggs!')
     @enclose
     def test3(string):
         print(string)
     @enclose(opt_func=some_func)
     def test4(string):
         print(string)
     test1()
     test2()
     test3('Python')
     test4('Rules!  ;)')
8<----------------------------------------------------------------

~Ethan~

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


Thread

Using decorators with argument in Python Jigar Tanna <poisonousrattle5@gmail.com> - 2011-06-28 09:52 -0700
  Re: Using decorators with argument in Python Lie Ryan <lie.1296@gmail.com> - 2011-06-29 03:06 +1000
    Re: Using decorators with argument in Python John Posner <jjposner@codicesoftware.com> - 2011-06-29 13:23 -0400
    Re: Using decorators with argument in Python Ethan Furman <ethan@stoneleaf.us> - 2011-06-29 12:30 -0700
    Re: Using decorators with argument in Python Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-29 13:29 -0600
    Re: Using decorators with argument in Python Ethan Furman <ethan@stoneleaf.us> - 2011-06-29 14:29 -0700
    Re: Using decorators with argument in Python Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-29 15:26 -0600
    Re: Using decorators with argument in Python Ethan Furman <ethan@stoneleaf.us> - 2011-06-29 14:51 -0700
    Re: Using decorators with argument in Python Duncan Booth <duncan.booth@invalid.invalid> - 2011-06-30 09:00 +0000
    Re: Using decorators with argument in Python John Posner <jjposner@codicesoftware.com> - 2011-07-01 11:18 -0400
  Re: Using decorators with argument in Python Ian Kelly <ian.g.kelly@gmail.com> - 2011-06-28 11:20 -0600
  Re: Using decorators with argument in Python Ben Finney <ben+python@benfinney.id.au> - 2011-06-29 08:19 +1000

csiph-web