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:

def index() -> Iterator:
    """Index page, optionally HTTP chunk-streamed and formatted."""
    return Foo.get_instance().are_changes_locked()


B) explicit decorators within the function body

def index() -> 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)))
  • \$\begingroup\$ Around here, we generally don't like brevity. \$\endgroup\$ Commented Jul 1, 2019 at 2:20
  • \$\begingroup\$ 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. \$\endgroup\$
    – Hugo G
    Commented Jul 1, 2019 at 3:19
  • \$\begingroup\$ 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. \$\endgroup\$
    – AlexV
    Commented Jul 1, 2019 at 6:11
  • \$\begingroup\$ 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. \$\endgroup\$
    – Hugo G
    Commented Jul 1, 2019 at 6:57

1 Answer 1


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

def baz(value: T) -> T:
    return value


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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.