Aspect-oriented vs explicit style in Python Readability counts, but is very subjective. The following snippets are equivalent in functionality and turn a generator iterator into a chunked HTTP response in Flask. Which of those two patterns is more Pythonic, readable and convenient?

A) Aspect style with function decorators that change the return value:

@app.route('/')
@flask_response_decorator
@optional_streaming_decorator
@progress_log_decorator
def index() -&gt; Iterator:
    """Index page, optionally HTTP chunk-streamed and formatted."""
    return Foo.get_instance().are_changes_locked()


or

B) explicit decorators within the function body

@app.route('/')
def index() -&gt; flask.Response:
    """Index page, optionally HTTP chunk-streamed and formatted."""
    response = Foo.get_instance().are_changes_locked()
    return flask.Response(optional_iterator_to_stream(iterator_to_progress_log(response)))
Pythonic, readable and convenient


are all subjective and open to debate, even though "Pythonic" is less so than the others. That said, a simplified version may be illustrative. Comparing

@foo
@bar
def baz(value: T) -&gt; T:
    return value


to

def baz(value: T) -&gt; FooT:
    return foo(bar(value))


there are two issues with the former:


The final return type is now hidden in foo.
It is easy to confuse the layering - is baz(value) equivalent to foo(bar(baz(value))) or bar(foo(baz(value))) (or even baz(foo(bar(value))) in case of a novice)? Nested decorators come up so rarely that I would have to look at the documentation to be absolutely sure whether they were in the right sequence.


There seems to be two situations where multi-level decorators would be fine:


If they pass through the return value unchanged. A logger would be a typical example.
If the decorators are commutative, that is, their order doesn't matter for the outcome.