Some reasons why Python isn't as elegant as you thought
Came to know Python via the famous
article by Eric, where he
recommended Python as the first language for programmers. I followed the doc
from official website of Python, but the overall experience was not so
satisfying. (Not exactly sure why.) I didn’t pursue this language too much
afterwards, and the reason I told myself is that redundancy in this language,
namely the :
for introducing one block and the indentation inside one block.
CoffeeScript is one example that removes this redundancy.
Someone may call this nitpicking, so more reasons are required to show Python is the not as intuitive as one thinks. Luckily, I came across this article recently.
Among the ten mistakes, only three are language (syntax) related, which do not have very intuitive semantics. Therefore, one get surprising outcome. The rest are problems existing in practice. (As one theorist, I don’t deal with problems in reality.)
-
OOP related. (#2 Using class variables incorrectly) It feels weird to use OOP in one scripting language, so I will skip this category.
-
Exception related. (#3 Specifying parameters incorrectly for an exception block) Exceptions maybe very useful in production code, but I have never written any production code, so I can’t comment on this category.
-
Programmer related. (#5 Modifying a list while iterating over it #7 Creating circular module dependencies) It’s just wrong in any languages, so what I can say…
-
Module related. (#8 Name clashing with Python Standard Library modules)
-
Compatibility related. (#9 Failing to address differences between Python2 and Python3)
-
Hidden stuff related. (#10 Misusing the
__del__
method) I guess it’s not meant to be used, for it has this weird prefix.
§function default arguments
Personally, I expect the code does what it seems to do, but I am wrong for Python. (I didn’t even bother myself to find out the “why” for Python.)
def foo (bar = [])
bar.append("baz")
return bar
Running above Python program in the repl:
>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
>>> foo()
["baz", "baz", "baz"]
Fortunately, CoffeeScript is intuitive this time.
foo = (bar = []) -> bar.push 'baz'; bar
>>> foo()
[ 'baz' ]
>>> foo()
[ 'baz' ]
>>> foo()
[ 'baz' ]
§scoping rules
This is pure stupid. Any reason to back up this design is excuse.
x = 10
def foo():
x += 1
print x
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment
Let’s see what the right way is:
x = 10
foo = ->
x += 1
console.log x
>>> foo()
11
§variables binding in closures
It’s actually one feature; variables are captured “by reference”.
x = [1..4].map (i) -> (x) -> x*i
y = (((x) -> x*i) for i in [1..4])
for f in x
alert f 1 # expected behavior
for f in y
alert f 1 # surprising behavior
As mentioned in the comment to the original post, generator is proposed as one solution to this problem. To be honest, it seems quite good, syntactically, but this generator syntax is too similar to list comprehension. It’s a matter of taste.