[Python-ideas] Where-statement (Proposal for function expressions)

Steven D'Aprano steve at pearwood.info
Sun Jul 19 04:08:57 CEST 2009


On Sun, 19 Jul 2009 06:11:57 am Gerald Britton wrote:
> >    items.sort(key=compute_sort_value) where:
> >> Now, the body of compute_sort_value appears exactly where it is
> >> executed: within the call to items.sort().
> >
> > No it doesn't. The function definition appears outside the call to
> > sort(). For the function definition to appear inside the call to
> > sort, you'd need to write something like
>
> Yes, it does appear within the call.  The call is more than just the
> parameters in parentheses.  It begins with "items.sort" and ends (in
> this case) with then end of the "where" clause

That's a definition of "within" that I'm not really happy with. And I 
think it's wrong. Consider the timing of calls:


import time
class MyList(list):
    def sort(self, *args, **kwargs):
        print "Call to sort() started at %s seconds" % time.time()
        super(MyList, self).sort(*args, **kwargs)
        print "Call to sort() ended at %s seconds" % time.time()

items = MyList([-9, 7, -4, 2, -1, 0, 3])
items.sort(key=func) where:
    print "Enter the where-block at %s seconds" % time.time()
    time.sleep(555)
    def func(item):
        return abs(item)


You need to create func before you can pass it as an argument to sort(), 
so I would expect the above to print something like:

Enter the where-block at 1234560000.23 seconds
Call to sort() started at 1234560555.24 seconds
Call to sort() ended at 1234560555.25 seconds

To my mind, to say that the contents of the where-block occur "within" 
the call to sort, it would imply that you get output like this:

Call to sort() started at 1234560000.23 seconds
Enter the where-block at 1234560000.24 seconds
Call to sort() ended at 1234560555.25 seconds


> >    items.sort(key=lambda item: value)
>
> The idea behind "where" clauses is not to replace lambdas.  In fact,
> they are useful together:
>
>      items.sort(key=mysort) where:
>          mysort =  sort_key_function_factory(
>                           with, many, arguments)


If you're going to say that where and lambda are useful together, 
shouldn't your example actually show where and lambda together?



> which to many is preferable over:
>
>     items.sort(key=lambda item:sort_key_function_factory(with, many,
> arguments))

That's equivalent to:

def f(item):
    function = sort_key_function_factory(with, many, arguments)
    return function

items.sort(key=f)

which almost certainly is not what you what.

I think what you meant was:

items.sort(key=lambda item:
           sort_key_function_factory(with, many, arguments)(item)
          )  # note that you call the function returned by the factory

which at least works, but it adds a pointless layer of indirection. What 
you should have is:

items.sort(key=sort_key_function_factory(with, many, arguments))

which of course is simpler than your earlier example with the 
where-block.



-- 
Steven D'Aprano



More information about the Python-ideas mailing list