# Aspect-oriented vs explicit style in Python [closed]

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('/')
@optional_streaming_decorator
@progress_log_decorator
def index() -> 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('/')
"""Index page, optionally HTTP chunk-streamed and formatted."""
response = Foo.get_instance().are_changes_locked()

• Around here, we generally don't like brevity. – Stephen Rauch Jul 1 '19 at 2:20
• I added docstrings. The code above is now exactly as it is in my project, except from the Foo class, which is irrelevant for this example. – Hubert Grzeskowiak Jul 1 '19 at 3:19
• You say yourself that it is subjective, that IMHO means its not a good fit for the kind of "objective" QA-style system here. In addition, you did not provide a lot of code to judge the code/differences in a greater context, which makes this question tend even more to the off-topic side of things. – AlexV Jul 1 '19 at 6:11
• I don't see how this question could possibly be off-topic. It is matched by the first point of on-topic examples: "If you have a working piece of code from your project and are looking for open-ended feedback in the following areas: Application of best practices and design pattern usage (...)". This question is about the usage of decorators for transforming the return value of a Flask view function and I provided a real piece of code I am using in production. – Hubert Grzeskowiak Jul 1 '19 at 6:57

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) -> T:
return value


to

def baz(value: T) -> FooT:
return foo(bar(value))


there are two issues with the former:

1. The final return type is now hidden in foo.
2. 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:

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