Nick Coghlan wrote:
On Mon, Jul 9, 2012 at 7:47 PM, Stefan Behnel <stefan_ml@behnel.de> wrote:
From an innocent look, I have no idea what the syntax is supposed to mean. Clearly doesn't hint at a factory for me.
I should also mention that I have a different proposal that affects the way one would write functions-that-returns-functions. I've been messing around with the idea of statement local namespaces for years (see PEP 3150) trying to find something that I consider better than the status quo, and PEP 403's statement local function and class definitions (http://www.python.org/dev/peps/pep-0403/) are the current incarnation.
With those, the number of statements in a simple wrapping decorator factory doesn't change, but the return statements can be moved above their respective function definitions:
def notify_on_call(callback, *cb_args, **cb_kwds): in return decorator def decorator(f): in return wrapped @functools.wraps(f) def wrapped(*args, **kwds): callback(*cb_args, cb_kwds) return f(*args, **kwds)
I *really* don't like the way that the "in return" statement reads like it creates a new block, but the following lines are not indented. If I were writing this as pseudo-code for a human reader, I would surely indent the following lines. Even if the part following the "in return" were limited to a single expression, I would prefer to indent it if it appears on another line. Using lambda as an example: # Best lambda x: expression # Acceptable lambda x:\ expression # Unacceptable lambda x:\ expression Looking back at "in return", here's a simple example which doesn't use nested functions. Compare: def function(arg): in return value value = process(arg) print("Value is", value) versus: def function(arg, verbose=False): in return value: value = process(arg) print("Value is", value) The lack of indentation (and trailing colon) makes the first extremely unpythonic -- everything else that creates a new block is indented. Consequently I hate the first one and am merely cold to the second.
Rather than the current out-of-order:
def notify_on_call(callback, *cb_args, **cb_kwds): def decorator(f): @functools.wraps(f) def wrapped(*args, **kwds): callback(*cb_args, cb_kwds) return f(*args, **kwds) return wrapped return decorator
I would not describe that as "out-of-order". Seems to me that it is precisely in order: first you create the object (a function), then you return it. You can't return something before it exists. It seems to me that this proposal, and the older PEP 3150, are the ones which are out-of-order: you use things before they are defined. For what it's worth, I have slightly warmed to PEP 3150 and would give it a very tentative +0.125: def notify_on_call(callback, *cb_args, **cb_kwds): return decorator given: def decorator(f): @functools.wraps(f) def wrapped(*args, **kwds): callback(*cb_args, cb_kwds) return f(*args, **kwds) return wrapped I don't think the above is any improvement at all on the status quo, but 3150 would allow you to write maths expressions more mathematically: def func(x): return a**2 + 3*a given: a = 1/(sin(x*pi)) + (cos(x)-1)/2 which I'm not sure will help people used to reading code, but it should at least be familiar territory to mathematicians and maths geeks. (Aside: I actually prefer that bikeshed to be called "where" rather than "given".) -- Steven