Until recently, Python had always been under tight moderation of its creator, Guido Rossum. While that had its good parts, the downside is the language’s slow development due to the bottleneck from the resistance of the creator.
For example, Guido Rossum distaste for lambdas was well-known. Perhaps the goal of Python’s half-baked lambda syntax that I’ve always found clumsy and useless to this day has always been to keep users from using it in the first place.
x = lambda a : a + 10
There is nothing wrong with this syntax, since many Lisp dialects also use the keyword lambda to initialize an anonymous function. However, being a whitespace-significant language and not expression-based, the lambda syntax of Python makes a cumbersome and ambiguous experience in applying lambdas:
x = lambda a : a + 10 (lambda b : b * 2))
Now who says Python is still easy to read? This kind of beats the very reasons of lambdas, which are expressiveness and clarity. This appears ambiguous to me. Compared to the anonymous function syntax of ES6:
let x = (c => c + 2)(a => a + 10)(b => b * 2)(y);
let x = y |> (c => c + 2) |> (a => a + 10) |> (b => b * 2)
Admit it, you either hate or feel meh over mapping iterables in Python, or you might not even use it.
let nums = [1, 2, 3, 4].map(n => n * 2);
Here is another map function in Rust:
let nums = [1, 2, 3, 4].iter().map(|n| n * 2);
Some functional languages such as Haskell and Ocaml use the
module:function approach, which is similar to what Python does. However, their expression-based syntax and unambiguous scoped variable binding makes the code readable and easy to get right. Here is a sample of a map function in Ocaml:
let nums = let double n = n * 2 in List.map double [1; 2; 3; 4]
You need to do this in Python:
double = lambda n : n * 2 nums = map(double, [1, 2, 3, 4])
You may think Python looks way cleaner here, which you may be right. But consider most use cases where you chain operators.
let nums = [1, 2, 3, 4] .map(n => n * 2) .filter(n => n > 2); .reduce((acc, current) => acc + current);
In Ocaml, it’s just magical:
let nums = [1; 2; 3; 4] |> map (fun n -> n * 2) |> filter (fun n -> n > 2) |> fold_left ( + ) 0
I’ll leave you to write an equivalent in Python (HINT: It is impossible to read!)
Decorators are my pet peeves. To me, they were the inflection point from Python mantra of “there’s only one way to do things” and the promise of a transparent, non-magical language.
def hello(func): def inner(): print("Hello ") func() return inner def name(): print("Alice") # `hello` is a decorator function obj = hello(name) obj() # prints "Hello Alice" The short-handed version for this is: @hello def name(): print("Alice") if __name__ == '__main__': name() # prints "Hello Alice"
Decorators “hide” the logic essential and completely change the behavior of a “host” function it decorates, which is nothing short of magical to more than half of all Python users today. Albeit useful, it still puzzles me to these days why Python developers decided to adopt decorators.