TL;DR: Author complains because he wants to program Java-style within Python, and he can't. He doesn't mention real outstanding things that Python needs to solve like the threading/async features versus the Global Interpreter Lock (GIL). No, just trivial stuff.

Detailed reply:

- The author complains: "Most obviously, there’s no such thing as ‘private’. The convention is to prefix things with an underscore, as a way of saying to the user, “don’t touch.”"

Yes, underscore is just a convention. But the author ignores that a good Python IDE, like PyCharm, will automatically and explicitly warn you whenever you're accessing an 'underscored' member from outside.

- "Python has lambdas, but they’re seriously hamstrung: They can only be a single expression. No statements."

The author ignores that functions are pretty much first class in Python. Thus, if you want a multi-line 'lambda', just define a function and pass it around. Yes, they will not be anonymous, but functions can be defined at any inner block, as well, so if you do it that way, you will have no name conflict problems. Very easy to do.

- The with statement. "If you had multi-statement lambdas in the language, you could do something like:"

I guess the author has not used Python enough, since the example he shows can be done in Python. As I mentioned, you can pass a function as an argument pretty easily.

- "Decorators, on the other hand, are just a band-aid over the lack of multi-statement lambdas."

The author hasn't got a clue of what is the usefulness of decorators.

- Again, complaining about decorator use in Flask:

from flask import Flask

app = Flask(__name__)

@app.route('/'):
def index():
return 'Hello, World!'

The author complains that he needs to define a name for index(), while this isn't needed in Ruby (under Sinatra).

Well, the author should use the Flask framework a little bit more before complaining, because the reason one needs to define a name for the index() function is to be able to... refer to this function later in many occasions!! For example, if i want to get the actual URL that is routed to index() i can use:

url_for('index')

In this way, you can separate the routes from the view controllers, and thus, you can change the route paths without having to break many parts of the code.

- The rest of the article, the author complains that Python "does not have a Type System". However, the author conveniently ignores many things:

a. Python allows to call functions using keyword arguments, which strongly helps preventing bugs since the order of parameters is not going to affect the code and you clearly know what input parameters are you assigning values too.

b. You can always insert assert() statements to have a form of type checking. A good IDE, like PyCharm, will then warn you whenever you are calling a function with wrong types, and in runtime the type error will be catched as well.

c. If you want static typing at 100%, why are you using Python? Wrong choice.

d. There is a specific documentation style that, if you're using PyCharm or another decent IDE, will show you the documentation for every parameter as you are writing your function call. If, having this feature, the coder still makes mistakes calling a function with wrong parameter types, then the coder is too stupid to use Python.

e. Python is strongly typed, so a wrong input type to a function will cause a runtime error pretty soon, anyways. And, in my opinion, the bugs caused by type mismatches, in a strongly typed languaged, are trivial to solve. The bugs that worry me are the difficult to solve ones, the ones caused by wrong understanding of the problem, etc. Those bugs will never be prevented by a type system.