That's a perfect summary of my feeling towards it, too. If the PSF puts up a GoFundMe for sending Guido on a nice vacation of his choosing, I will be happy to chip in a few bucks. Same goes for Linus when he hands over the reins, and a few other maintainers who probably cannot be adequately compensated for the impact of their work.
After all those, I found Python, as the saying goes, really does "fit your brain" [1]. Since discovering Python 18 years ago, I have looked at Haskell, successfully avoided Java, and promised myself to "one day" do more JS. Still, Python remains 95% of what I do, and I don't see a problem with that :)
[1] "Python fits your brain" was the theme of the 9th International Python Convention in 2001.
For me, I find using python is like touching both data and code with my hands.
As much as it's trendy to bash Object Oriented languages, the way python allows to lookup all variables and method on a class or an object makes it like using your hands:
dir(MyClass) help(MyClass) dir(my_object) help(my_object)
etc...
[0] http://www.ccs.neu.edu/home/matthias/HtDP2e/index.html
[1] http://web.mit.edu/alexmv/6.037/sicp.pdf
[2]https://www.youtube.com/watch?v=2Op3QLzMgSY&list=PLE18841CAB...
I have looked at LISPs, but it's difficult to pick one to invest time in. Because I am so restricted on time I have to stick to languages which are used in the industry (so my fun has real-life ROI), which I think boils down to CL which is often touted as old-fashion and its market seems to shrink slowly, and Clojure which means the JVM and mainly Java libraries and high mem requirements.
For pure fun and practicality, Racket does seem up on the "list", but not used at all in the industry. A lot of languages (Python, Rust) are adopting the good parts of lisp (except for the minimal syntax, sadly), and I'm getting better mileage from spending time learning and becoming better at those than starting from scratch in a language that I won't be able to use during work hours.
That is what I hate most about Python, there is only one sure-fire way of doing packaging and that’s setting it up even before you write your first line of code and the testing constantly as your project evolves.
Myself and others have absolutely no trust in the several build pathways because they all fail horrible for a wide range of reasons. To the counter, if I have a C++ or C# project I’m very confident that it will almost always be a breeze to package it up.
x = 100
y = [x+i for i in range(2)]
In Python 3 I kept seeing NameError: name 'x' is not defined
However, after working around this problem with fixes like this - x = 100
y = (lambda x=x: [x+i for i in range(2)])()
I have just discovered that the different scope treatment was due to a problem with IPython when using it in embed mode, for example by calling it with the following command: $ python -c "import IPython;IPython.embed()"
It goes away when you call ipython directly $ ipython
I mistakenly attributed this problem to Python 3 for years, I guess I introduced the problem because I had a different way of invoking Python 2 and Python 3 - yeesh.Ironically, the PEP to add this to py3k is what's causing all the fuss in pythonland lately.
Can you elaborate? I'm not sure what this is referring to.
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> [a*2 for a in (1,2,3)]
[2, 4, 6]
>>> a
3
In Python 3.x, it is not: >>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> [a*2 for a in (1,2,3)]
[2, 4, 6]
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
It is sometimes useful to know why something failed. The following Python 2 code will not work in Python 3: >>> import math
>>> try:
... values = [math.sqrt(x) for x in (1, 2, -3, 4)]
... except ValueError:
... print("cannot compute sqrt(%r)" % x)
...
cannot compute sqrt(-3)
I have mostly found this feature of Python 2 to be useful on the interactive shell, when trying to diagnose what caused an error in my list comprehension. Eg. >>> with open("tmp.dat") as input_file:
... fields = [line.split()[3] for line in input_file]
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
>>> line
'one two three\n'
Oops, there are only 3 columns, not 4. [a := x*2 for x in (1, 2, 3)]
See PEP 572 -- Assignment Expressions: https://www.python.org/dev/peps/pep-0572/I often did:
>>> [d for d in drawings]
>>> [d.<tab> ...]
Because I’m lazy and I want the autocomplete to be there for me. It’s actually the only thing I miss from python 2 and I will admit that a couple of times the sideffects have caught me out in production code so I’m happy with the change.It’s worth noting that the latest python pep is going to give you a way to assign the variables in the outer scope again:
https://www.python.org/dev/peps/pep-0572/#simplifying-list-c...
In Python 3, it raises a NameError, because the x in "print(x)" is not defined. It's contained in the list comprehension.
But I don't know a good use of the Python 2 behavior.
Recently I started trying to learn swift through the Stanford course. And the curly brackets confused the heck out of me. They still do! They just seem to pop up out of nowhere. All to say , I completely agree with your second paragraph. Python is very concise.
C/C++/Java use them quite a bit.
It's syntactically concise because of its use of whitespace and indentation instead of curly braces.
Expressions are often concise because of things like list slicing and list expressions.
It can be linguistically concise, because it is so easy to fiddle with the data model of your classes, to customize their behavior at a deeper level. For example, it is so quick to design a suite of classes that have algebraic operators, which leads to elegant mathematical expressions of your custom GUI objects for example. But you can also change the way classes are instantiated by overriding Class.__new__ which I've used to make powerful libraries that are a joy to use.
Further elegance can be added through creative use of the flexible argument passing machinery, and the lovely way that functions are also objects.
Your application architecture tends to be concise because there are so many existing libraries, you can often design your application at a more interesting higher level. For example, you don't have to worry about the size of int's.
My big regret with Python 3.0 is that the scoping rules in list expressions changed to prohibit modification of variables in surrounding scope. This degraded the utility of list expressions. The work around is so long-winded.
Besides the odd gripe here and there, the language really gives me a warm glow.