[Python-ideas] Allow lambda decorators

Guido van Rossum guido at python.org
Mon Feb 9 18:09:18 CET 2009


On Sun, Feb 8, 2009 at 8:08 PM, Carl Johnson <carl at carlsensei.com> wrote:
>
> On 2009/02/08, at 5:29 pm, Guido van Rossum wrote:
>
>> I'm sorry, but you are using two nested lambdas plus a list
>> comprehension, and three nested functions here, plus one more list
>> comprehension for showing the result. My brain hurts trying to
>> understand all this. I don't think this bodes well as a use case for a
>> proposed feature.
>>
>> I'm not trying to be sarcastic here -- I really think this code is too
>> hard to follow for a motivating example.
>
> I will admit that this is getting a bit too functional-language-like for its
> own good, but (ignoring my proposed solution for a while) at least in the
> case of the nested scope problem, what other choices is there but to nest
> functions in order to keep the variable from varying? I myself was bitten by
> the variable thing when I wanted to write a simple for-loop to add methods
> to a class, but because of the scoping issue, it ended up that all of the
> methods were equivalent to the last in the list. At present, there's no way
> around this but to write a slightly confusing series of nested functions.

Are you unaware of or rejecting the solution of using a default argument value?

[(lambda x, _i=i: x+i) for i in range(10)]

is a list of 10 functions that add i to their argument, for i in range(10).

> So, that's my case for an each_in function. Going back to the @lambda thing,
> in general, people are eventually going to run into different situations
> where they have to write their own decorators. We already have a lot of
> different situations taken care of for us by the functools and itertools,
> but I don't think the library will ever be able to do everything for
> everyone. I think that the concept of writing decorators (as opposed to
> using them) is definitely confusing at first, since you're nesting one thing
> inside of another and then flipping it all around, and it doesn't entirely
> make sense, but the Python community seems to have adapted to it. For that
> matter, if I think too much about what happens in a series of nested
> generators, I can confuse myself, but each individual generator makes sense
> as a kind of "pipe" through which data is flowing and being transformed.
> Similarly, metaclasses are hard to understand but make things easy to use.
> So, I guess the key is to keep the parts easy to understand even if how the
> parts work together is a bit circuitous. Maybe @lambda isn't accomplishing
> that, but I'm not sure how much easier to understand equivalent solutions
> would be that is written without it. Easy things easy, hard things possible?

I don't see what @lambda does that you can't already do with several
other forms of syntax. The reason for adding decorators to the
language is to have easier syntax for common
manipulations/modifications of functions and methods. A decorator
using lambda would be a one-off, which kind of defeats the purpose.
For example, instead of this:

>>> def func_maker():
...     @lambda f: [f(i) for i in range(10)]
...     def fs(i):
...         def f():
...             return i
...         return f
...     return fs #Warning, fs is a list, not a function!
...

I would write this:

  def func_maker():
    def fi(i):
      def f():
        return i
    fs = [fi(i) for i in range(10)]
    return fs

In regard to the proposal of "bind i" syntax, I have a
counter-proposal (as log as we're in free association mode :-):

Define new 'for' syntax so that you can write

  [lambda: i for new i in range(10)]

or e.g.

  fs = []
  for new i in range(10):
    def f():
      return i
    fs.append(f)

The rule would be that "for new <name> in ..." defines a new "cell"
each time around the loop, whose scope is limited to the for loop. So
e.g. this wouldn't work:

  for new i in range(10):
    if i%7 == 6:
      break
  print i    # NameError

I'm not saying I like this all that much, but it seems a more Pythonic
solution than "bind i", and it moves the special syntax closer to the
source of the problem.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-ideas mailing list