7 ms·
A better reason to hate Python: the internal model is way overcomplicated for what it's meant to be: a beginner-friendly scripting language. "Everything-is-an-o
by colanderman 8y ago
A better reason to hate Python: the internal model is way overcomplicated for what it's meant to be: a beginner-friendly scripting language. "Everything-is-an-object", duck typing, decorators, bizarre scoping rules, etc., all make it difficult for experienced programmers to understand, let along beginners. I've always thought there's a much simpler language struggling to get out of Python, and I wish it would and would become popular so I wouldn't have to recommend Python to beginners any more, and be on the hook for explaining e.g. why default values are mutable, or why nested generator comprehensions behave differently than nested list conprehensions. (Think Erlang levels of simplicity.)
The standard library is also haphazard and inconsistent (much like JavaScript's). Take lists: some operations are methods, some are functions, some mutate the list, some make a copy, some are global, some are in a module. There's no rhyme or reason that I can tell. Modern C++ has, in my opinion, a much more well-thought-out standard library. There are very few methods/functions which exist due to historical accident (iostreams aside), and the distinctions between methods/free functions and mutators/copiers is fairly uniform.
- mannykannot 8y agoThe C++ standard library is (mostly) an exemplary work, but that is despite the language's complexity, with pointers and lvalue, rvalue and forwarding references, just to get started...
- colanderman 8y agoOh completely agreed. C++ the language is as or more complex/overcomplicated as Python. (Hence my example of Erlang as a simple language.)
- qntty 8y agoIs python really meant to be a beginner-friendly language? I tend to think of it as lisp-without-parens, and lisp is not very beginner friendly.
- cschmidt 8y agoIt is usually the "first language" of choice these days, when teaching programming.
- monadgonad 8y agoThat does not mean beginner-friendliness is one of its design goals.
- alayne 8y agoIt was though https://www.artima.com/intv/pyscale.html https://www.artima.com/intv/pyscale.html "So I never intended Python to be the primary language for programmers, although it has become the primary language for many Python users. It was intended to be a second language for people who were already experienced programmers, as some of the early design choices reflect. On the other hand, intuitively I probably stuck to many of ABC's design principles. Because although I had my criticisms of ABC, I borrowed many of its valuable elements, which eventually made Python a great language for people who aren't ace programmers or who are just learning. We now have a large community of people using Python as an educational language, teaching Python in schools. These people aren't and may never be professional programmers, but they still find some programming skills useful." -GvR
- deleted 8y ago[deleted]
- sidenoteproof 8y agoThe very quote you linked explicitly contradicts you... "It was intended to be a second language for people who were already experienced programmers, as some of the early design choices reflect. "
- deleted 8y ago[deleted]
- 8y ago
- rciorba 8y ago> Take lists: some operations are methods, some are functions, some mutate the list, some make a copy, some are global, some are in a module. Let's take the list type, the public methods are: 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort' Obviously as the names imply `copy` returns a new list, and `count` returns an integer. Neither mutate the list. For the rest of it: methods mutate the list. There are some builtin functions that do similar things, but those always a new object (sorted, reversed)
- colanderman 8y agoOK, fair point. I misremembered the list interface. `set` is a better example: `set.union`, for example, returns a new set, while `set.add` updates in place. (To be fair, this is with Python 2.7, maybe Python 3+ is more uniform?)
- acdha 8y agoWhat would you expect it to do differently in those cases? That seems like the API is following how most people would think about those operations as you'd expect in a language which isn't trying to be immutable.
- pfranz 8y agoI thought it was interesting that Ruby, by convention, used an exclamation mark to convey that a function would mutate. I haven't used Ruby all that much to see how well that works at scale.
- deleted 8y ago[deleted]
- pseudalopex 8y agoMany libraries don't use it. Another convention uses it for methods that might raise an exception.
- int_19h 8y agoA great "simple beginner language" would be Lua, if only it had a decent standard library.
- tln 8y agoI think a simpler language would also have more potential for speedup. The effort PyPy has invested is herculean! Grumpy, Cython, Unladen Swallow, etc. Python has fallen to my second or third most commonly used language now and speed is definitely a reason.
- spenrose 8y ago"I wouldn't have to recommend Python to beginners any more, and be on the hook for explaining e.g. why default values are mutable, or why nested generator comprehensions behave differently than nested list comprehensions." Maybe those scoping gotchas are not beginner topics?
- detaro 8y ago> Maybe those scoping gotchas are not beginner topics? They are the second one of your beginners trips over them. Especially the first one is fairly easy to encounter and really vexing. That said, Python in my experience is an excellent beginner language, and I'd still recommend or teach it.
- deleted 8y ago[deleted]
- bakery2k 8y ago> I've always thought there's a much simpler language struggling to get out of Python I agree, although I suspect we have different ideas as to which parts of Python would be included in that simpler language. For example, I quite like the consistency of "everything-is-an-object". FWIW some of the Python core developers have started to express a similar sentiment. Especially in the last few versions, where Python has got much more complex with the addition of type annotations and multiple `async/await` features. I wonder whether the retirement of the BDFL will slow down Python's rate of growth, or accelerate it? > nested generator comprehensions behave differently than nested list conprehensions I haven't come across this - could you give an example?
- colanderman 8y agoSure: >>> [[x*y for y in xrange(1,5)] for x in xrange(1,5)] [[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]] >>> list([x*y for y in xrange(1,5)] for x in xrange(1,5)) [[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]] >>> [list(l) for l in ((x*y for y in xrange(1,5)) for x in xrange(1,5))] [[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]] >>> [list(l) for l in [(x*y for y in xrange(1,5)) for x in xrange(1,5)]] [[4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16]] The problem is that the `x` in the inner comprehension gets somehow linked to the variable `x` in the outer comprehension, rather that the value of `x`. (This matches Python's similarly bizarre closure semantics.) So, the results are "as expected" when either (a) the inner comprehension is evaluated eagerly (first and second example), or (b) the outer comprehension is evaluated lazily (second and third examples). But if both the inner and outer comprehensions are evaluated lazily, the inner comprehensions just see whatever the "last" value of `x` was, which I think to many people is surprising. (No less so than mutable default arguments, at least.)
- bakery2k 8y agoYou're right, this is the same problem that Python has with closures, for example: >>> l = [] >>> for i in range(10): ... l.append(lambda: i) ... >>> for j in range(10): ... print(l[j](), end=' ') ... 9 9 9 9 9 9 9 9 9 9 The issue isn't really closing over the variable instead of the value, but the fact that Python re-uses the same variable for each iteration of the loop. C# used to behave the same way, but its designers considered this bad enough that they made a breaking change to the language to fix it [1]. Unfortunately, C#'s solution (creating a new variable for each execution of the loop body) isn't really an option for Python. It would conflict with the rest of the language, which only uses variables scoped to whole functions. Note that Go makes the same mistake as in earlier versions of C# [2]. [1] https://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/ https://ericlippert.com/2009/11/12/closing-over-the-loop-var... [2] https://play.golang.org/p/Pt6BN2Mj-WL https://play.golang.org/p/Pt6BN2Mj-WL
- tzs 8y ago> I've always thought there's a much simpler language struggling to get out of Python [...] I tend to assume that about all languages now, and when I need to use a new language I try to just learn that simpler language initially. I skim the documentation for the rest, but don't learn it until I actually need it (either because the functionality is necessary, or it can make the code better). It can take a surprisingly long time to need more than the simple language.
- mixmastamyk 8y agoBelieve this is largely due to history, ie. the agile manifesto point of not knowing enough until it is done. I'd also welcome a simplified Python, from scratch as it were, but that is a giant undertaking and bigger than the 2 to 3 chasm.