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


Groups > comp.lang.python > #89438 > unrolled thread

Function decorator having arguments is complicated

Started byMakoto Kuwata <kwa@kuwata-lab.com>
First post2015-04-27 11:37 +0900
Last post2015-04-29 21:22 +1200
Articles 3 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Function decorator having arguments is complicated Makoto Kuwata <kwa@kuwata-lab.com> - 2015-04-27 11:37 +0900
    Re: Function decorator having arguments is complicated Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-04-27 17:36 +1000
      Re: Function decorator having arguments is complicated Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2015-04-29 21:22 +1200

#89438 — Function decorator having arguments is complicated

FromMakoto Kuwata <kwa@kuwata-lab.com>
Date2015-04-27 11:37 +0900
SubjectFunction decorator having arguments is complicated
Message-ID<mailman.31.1430102277.3680.python-list@python.org>

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

I want to ask Python experts about function decorator which has arguments.

I feel that function decorator having arguments is complicated,
because three 'def' are nested:

  def multiply(n):
    def deco(func):
      def newfunc(*args, **kwargs):
        return n * func(*args, **kwargs)
      return newfunc
    return deco

  @multiply(4)
  def f1(x, y):
    return x+y

  print(f1(2, 3))   #=> 20  (= 4 * (2+3))


If function decorator notation could take arguments,
decorator definition would be more simple:

  def multiply(func, n):
    def newfunc(*args, **kwargs):
      return n * func(*args, **kwargs)
    return newfunc

  @multiply 4      # ex: @decorator arg1, arg2, arg3
  def f1(x, y):
    return x+y


How do you think about this idea?

--
regards,
makoto kuwata

[toc] | [next] | [standalone]


#89450

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-04-27 17:36 +1000
Message-ID<553de6f1$0$12905$c3e8da3$5496439d@news.astraweb.com>
In reply to#89438
On Monday 27 April 2015 12:37, Makoto Kuwata wrote:

> I want to ask Python experts about function decorator which has arguments.
> 
> I feel that function decorator having arguments is complicated,
> because three 'def' are nested:
> 
>   def multiply(n):
>     def deco(func):
>       def newfunc(*args, **kwargs):
>         return n * func(*args, **kwargs)
>       return newfunc
>     return deco

Yes. But not that complicated -- it is only three levels, and the pattern is 
pretty simple:

- outer function takes arguments and returns a decorator;
- middle function is the decorator to be returned;
- inner function is the new function returned by the decorator.

So we start with a regular decorator:

def deco(func):
    def newfunc(*args, **kwargs):
        return n * func(*args, **kwargs)
    return newfunc

indent it one more level, and wrap it in a function:

def multiply(n):
    # as above, indented one extra level


What's really tricky is a decorator which can *optionally* take arguments or 
not:

@decorator(x, y)
def function(): ...


# not the same as @decorate()
@decorate
def function(): ...


> If function decorator notation could take arguments,
> decorator definition would be more simple:

Yes, but then we have to learn more syntax:

@decorate
@decorate n
@decorate(n)
@decorate()  # uses the default for multiply

could all be different.

Although I agree with you that writing a decorator factory is a bit 
complicated, it is simple to break it up into individual sub-steps:

* I know how to write a function that adapts or wraps another 
  function.

* I know how to write a decorator: write a function, indent it 
  one extra level, and wrap it in an outer function;

* I know how to write a decorator factory: write a decorator, 
  indent it one extra level, and wrap it in an outer function;

which could even be extended:

* I know how to write a decorator-factory factory: write a 
  decorator factory, indent it one extra level, and wrap it 
  in an outer function.


Saving one layer is not important enough to justify specialised syntax.



-- 
Steve

[toc] | [prev] | [next] | [standalone]


#89535

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2015-04-29 21:22 +1200
Message-ID<cqbm6bFdooeU1@mid.individual.net>
In reply to#89450
> On Monday 27 April 2015 12:37, Makoto Kuwata wrote:
> 
>>  def multiply(n):
>>    def deco(func):
>>      def newfunc(*args, **kwargs):
>>        return n * func(*args, **kwargs)
>>      return newfunc
>>    return deco

I'd like to be able to write that as

    def multiply(n)(func)(*args, **kwargs):
       return n * func(*args, **kwargs)

-- 
Greg

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web