You may not like it, but it's not an error, it's a design decision.
> Python is a very powerful dynamic language. It lets you code with any paradigm that suits the problem you’re trying to solve. Functional, OOP, procedural, or whatever.
Which simply isn’t true (as is proven by you as well) — Python was never designed to “let you code with any paradigm that suits the problem”. It has severely limited functional and (nonexistent?) metaprogramming capabilities, so the claim might be better phrased as follows:
> Python is a very powerful dynamic language. It lets you code with any paradigm that suits the problem you’re trying to solve, as long as it’s OOP.
(Please excuse the sarcasm: I work with Python and I like it for its simplicity, good tooling and a myriad of other things, but “flexibility”, for a lack of a better word — especially compared with LISP — is not one of them.)
In my mind, the following is better than the JS equivalent using closures:
response = await AsyncHTTPClient().fetch("http://www.google.com")
self.result = json.loads(response.payload)
You see exactly what is going on, no additional nesting, and no need for semi-inner state that potentially complicates state reasoning. I.e. people get tempted to put code afterwards thinking it'll run after the previous line.I may get some flack for this or my language, but I have absolutely no idea why anyone bothers so much with the closure garbage outside of select places where they make sense. It's non-intuitive and looks bad. Heck, I have a bad enough time explaining to seasoned devs the difference between threads and async concepts. Then you throw that sort of stuff at a junior JS dev and chaos will most certainly ensure with a buggy FE where no one can reason about state and there are null checks all over the place, just because. I've seen it in static FE languages like C#, too. State becomes too difficult to reason about, so null-checks are required everywhere.
Edit. Formatting.