Live data from Hacker News

Python is not a great programming language

gist.github.com

81–90 of 156 posts

Re: Python is not a great programming language

#81
post #67

Earlier quoted context omitted.

>Either way, if the number of idiosyncracies in your language is confusing to junior developers it's absolutely something worth considering. Why? Aiming for the lowest common denominators and the simplest systems tends to not create scalable long term solutions. You also seem to really undercount what a properly trained junior developer is capable of understanding.

Most popular programming languages got popular by aiming for the LCD in some capacity, e.g. Java. It's the reason why we're not all writing LISP or Haskell.

I don't think Python has any issues with popularity.

Re: Python is not a great programming language

#82

Sure Python has many problems, but these aren't a great selection. > The syntax for classical inheritance. Half of each Django app is super().__init__( args, *kwargs). At least you don't have to pass arguments to super anymore. Yes, inheritance is hard to do well, but that's generally true. Much better to prefer composition ( https://en.wikipedia.org/wiki/Composition_over_inheritance ) > Too many magic __double-under…

Sure Python has many problems, but these aren't a great selection.

Yes. I have my disagreements with Python, but those are not it. The article author is mostly complaining about ways Python differs from Javascript.

- Agree that the mechanism for talking about parent classes wasn't very good. Multiple inheritance usually adds complication without adding much necessary functionality. That's not just a Python problem. It's a leftover from viewing objects through an "A is-a B" lens, one of the dead ends of early AI.

- Python has too much gratuitous dynamism. Any thread can find and mess with any code and data in another thread. The implementation has to support that, which knocks out many valuable optimizations. The language model, and the original implementation, use "everything is a dict", which implies "slow".

- One consequence of the above is Python's terrible one thread at a time thread system, with the "global interpreter lock". The "multiprocessing" hack to get around that is ugly and uses too much memory, since each subprocess has its very own Python system instance. To some extent, the "async" add on is yet another hack to get around the limits of threading.

- Another consequence is a tendency to call C code where Python performance is terrible. The C code has to carefully obey the rules of the Python system. Mostly it does.

- Optional typing is a marginal idea, but unchecked marginal typing is just weird. Language design seems to be converging on implicit static typing - result variables are automatically typed whenever possible. Go, Rust, and now C++ (with "auto") took that route.

- And, of course, the botched Python 2 to 3 transition set Python back for a decade.

On the other hand, Python exceptions work out well. A reasonably sane exception hierarchy helps. Although the one for 2.x was better than the one for 3.x; the 2.x one made a clear distinction between external problems ("Environment errors") and internal problems.

The "with" clause system plays well with exceptions, and nested exception failures unwind correctly. It's far better than Go's "defer". C++ and Rust try to handle this sort of thing with RAII, which never handles trouble in a destructor well.

Re: Python is not a great programming language

#83
post #66
post #6

This list is so deliciously sophomoric. The best one is, and I quote: """To many other weirdo bits of magic syntax, like [list comprehensions]""" Obviously without actually proposing how comprehensions could be made better one has to hope the author would say he likes the equivalent Haskell better, but there is a strong doubt that is not the case.

" Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something. " https://news.ycombinator.com/newsguidelines.html For example, instead of putting someone's article down as sophomoric, you could explain what's different and possibly better about Haskell list comprehensions.

You could, but you'd lose the Socratic method and efficiency of thinking. There is a reason why many academics can be quite acerbic.

All these politeness comments are a speed bump that distracts from the real issues.

Re: Python is not a great programming language

#84
post #60

Earlier quoted context omitted.

I personally find list comprehensions in python pretty horrible. They seem to exist only to do lots of stuff in one single line of code. You end up with totally impenetrable unreadable perl-esq garbage write-once-read-never code that is too clever for its own good. And people say python is easy to learn and good for beginners...! A better approach would be something like Java Streams/.net Lync/RxX pattern IMO. Explic…

dic = {k: v for k, v in dic.items() if k in other_dic and v == "bar"} How could that be improved? That's 3-4 LOC minimum in any other language My main grip is python's ternary operators, since the True value is evaluated before the condition, if you are doing ternaries on things that might throw exceptions the False value has to come first value = 0 if key not in dic else dic[key] * 5 rather than (throws indexerror i…

    dic = {k: v for k, v in dic.items() if k in other_dic and v == "bar"}
> "How could that be improved? That's 3-4 LOC minimum in any other language"

If I'm understanding the comprehension correctly,

    (into {} (filter (fn [[k v]] (and (get other-dic k) (= v "bar"))) dic))

Though, for readability, I'd likely write it as:

  (->> dic
       (filter (fn [[k v]]
                 (and (get other-dic k)
                      (= v "bar"))))
       (into {}))
Legibility is in the eye of the beholder.

Re: Python is not a great programming language

#85
post #84
post #60

Earlier quoted context omitted.

dic = {k: v for k, v in dic.items() if k in other_dic and v == "bar"} How could that be improved? That's 3-4 LOC minimum in any other language My main grip is python's ternary operators, since the True value is evaluated before the condition, if you are doing ternaries on things that might throw exceptions the False value has to come first value = 0 if key not in dic else dic[key] * 5 rather than (throws indexerror i…

dic = {k: v for k, v in dic.items() if k in other_dic and v == "bar"} > "How could that be improved? That's 3-4 LOC minimum in any other language" If I'm understanding the comprehension correctly, (into {} (filter (fn [[k v]] (and (get other-dic k) (= v "bar"))) dic)) Though, for readability, I'd likely write it as: (->> dic (filter (fn [[k v]] (and (get other-dic k) (= v "bar")))) (into {})) Legibility is in the eye…

Each to their own, but both the snippets you posted crossed my threshold for headache inducing parentheses tracking

Re: Python is not a great programming language

#86
It's certainly not a perfect language (no multi-line lambdas, double underscore keywords everywhere, converting generators, significant white space means problems working in other environments, typing, isn't called lisp), but you know what...

I've been pleasantly surprised how shallow the "general python rabbit-hole" is.

If i can express this in words, one of the ways I like to judge a language when I program: i think of something a computer could theoretically do, then I look for ways to express it in that language. How many independent jumps I have to take down the conceptual rabbit-hole before I get to the solution is a nice little arbitrary metric.

Does python do everything the way I'd do it? No. You get over yourself and just accept that's the way it is in this language.

Once I've done that, so far most problems in python have been pretty shallow: do this arbitrary thing and then this arbitrary thing and you're done.

Compared to some of my past languages where you have to go 4 or 5 levels deep with N compulsory but conceptually irrelevant steps, it's pretty damn good. Makes for a reasonable quick pathway to actually getting anything done...

Purely my subjective opinion.

Re: Python is not a great programming language

#87
post #73

Part of the problem here is clearly this person is mapping JavaScript idioms to python; in particular "Needing to put dict property names `{'in': 'quotes'}": these aren't object properties , these are keys in a map, and they can be and often are variables themselves, (also, can be any hashable type, not just strings) and I don't see how that can detract from the 'greatness' of python. Also "foo['bar'] returns a KeyEr…

> "Different syntaxes for lists and tuples." -- Again, what? They're different types!

Lists and tuples have different syntax in a weird and surprising way. List syntax is straightforward, just square brackets and commas. Tuple syntax pretends to be list syntax with parentheses but it's actually only about commas except when it isn't.

Typically you write `(a, b)`, but the parentheses are only for precedence, and can be left out if it's unambiguous: `a, b`. You can write a 1-list as `[a]`, but a 1-tuple is `(a,)` because `(a)` is just `a`. An empty tuple on the other hand is `()`, without any commas, and with parentheses doing something other than precedence. It's very ugly.

I can't think of a better way to fit it into the rest of the syntax but I still count it as a flaw.

Re: Python is not a great programming language

#88
post #85
post #84

Earlier quoted context omitted.

dic = {k: v for k, v in dic.items() if k in other_dic and v == "bar"} > "How could that be improved? That's 3-4 LOC minimum in any other language" If I'm understanding the comprehension correctly, (into {} (filter (fn [[k v]] (and (get other-dic k) (= v "bar"))) dic)) Though, for readability, I'd likely write it as: (->> dic (filter (fn [[k v]] (and (get other-dic k) (= v "bar")))) (into {})) Legibility is in the eye…

Each to their own, but both the snippets you posted crossed my threshold for headache inducing parentheses tracking

Similarly, my parsing of special-case syntax in the Python.

Re: Python is not a great programming language

#90
post #53
post #25

Earlier quoted context omitted.

It is annoying! And doesn't always save memory. In theory a "sufficiently smart language" should have a feature to understand that `thing[3]` can be translated to "call `next()` 3 times and gimme the last thing", not in "turn this completely to a list, that may take a ton of memory, although I only need that one third element". Generators should be treatable as lazy lists in the end, and lists should have a common in…

You don't need to cast the generator, you can do: next(itertools.islice(my_generator, n, n+1)) With that said... > In theory a "sufficiently smart language" should have a feature to understand that `thing[3]` can be translated to "call `next()` 3 times This might be a newbie trap, because next() isn't the same as indexing. What happens if I perform `thing[7]` followed by `thing[5]`? Should performing `thing[7]` put 1…

> Should performing `thing[7]` put 1-6 in memory and turn the object into a generator-list hybrid

You're right here. Probably can't work like that since generators are too general, you can't expect them to be rewindable or to not have side effects... prob you'd need a more specialized concept like a "lazy list" that would be a subtype of generator with some extra restrictions that would make it possible to implement the "hybrid" structure as an implementation detail without changing semantics.

Anyway... it would be too much work and probably would turn into a footgun.

Post reply on HN