back
171 comments
Quite a few poor and superficial answers in that link. The usual argument that dynamic typing does not scale for large projects is largely unfounded. There are large projects in Lisp, I don't get why people don't use the dynamic card as often there. What I have seen happened on badly engineered large projects is people blaming it on dynamic typing because there is no documentation and no structural integrity in the project. But the people behind those projects would not be able to do much in any language IMO. In a sense, it allows for poor programmers to do more.

The speed issue is a significant one, but not usually for the reasons given. The big drawback of being slow means a lots of its implementation is not written in python.

IDE/debugger is another issue, although some of it is a matter of people not knowing the tool. Especially on bad codebases, even something as simple as pyflakes running in the background is invaluable, and many people don't use this.

What I have seen happened on badly engineered large projects is people blaming it on dynamic typing because there is no documentation and no structural integrity in the project.

This can be a problem in static languages with good type inference, too. When reading code in older static languages like C++, you'll find a bunch of variables and types declared, but powerful and concise languages such as Scala have much less use for intermediate variables, and type inference means that intermediate variables are almost never declared with a type. Field types and method return types often aren't declared either. I don't know if this is a good thing because it forces you to read a lot of code, or if it's a bad thing because it forces you to read many unrelated bits of code when you're trying to get something simple done.

I've been digging into Clojure and reading Paul Graham's On Lisp. So I've been wondering about Python vs. Lisp lately, esp. on the topic of dynamism. I wish I knew more about Lisp to delve into this further, but your first para caught my eye.

Is it not the case that in Lisp people tend to use values — lists of (probably immutable) data — rather than objects? Objects are in and of themselves their own flavor of custom, specialized language for interacting with a data structure. In Lisp, the language for interacting with lists of lists or what have you is, well, Lisp.

IME duck typing is not a real answer in this situation; that helps when you are programming to an interface in the standard library, or in an API you are using. Otherwise I end up hunting down information about a data type through N layers of method and function calls. Not a good time. :( This actually drove me towards Go as a language with comparable productivity but with a type checker, et al.

I'm not sure where Lisp macros fit into this, if they do. I expect they have a tendency to boil down frequently repeated patterns into something very compact and less error-prone.

As for IDE support, Rob Pike suggested (not in so many words) that if you need an IDE for your programming language, it suggests that something's probably wrong with that language. He's not disputing that people genuinely need them, because yes, jesus h, I really do need Eclipse when you're programming against a reasonably large API. I think I find this line of reasoning more convincing than I would have, say, a year or two ago.

Anyway, for my part, ST2 was enough of a Python IDE for me. And thanks for the tip about Pyflakes, by the way. There's guard[1], which I figured you could rig up with python -c or whatever the flag is to compile. Pyflakes looks easier.

[1]: https://github.com/guard/guard

In a sense, it allows for poor programmers to do more.

Exactly. Dynamic typing can provide a temporary fig leaf for bad design in ways where static type checking would be less forgiving. Doesn't make dynamic typing wrong, it just means that bad programmers can get in over their heads more completely and more quickly.

Python has been my favorite language for many years, while the last few months at work I've been writing a lot of JavaScript. I've found that JS has exactly one advantage over Python, which is usable function literals. And that turns out to have a surprisingly large impact. It's convenient and natural to create "anonymous classes" that use closures to store their state, while in Python you'd have to manually create classes and manually copy the variables in __init__. I really wish Python could gain something like that while retaining its many advantages.
What do you mean by "usable function literals"? Because Python has them, even if you have to do a bit of work to get them.

    def demo (n):
        def multiplier (m):
            return n * m
        return multiplier

    x5 = demo(5);
    print x5(4)
You can do anything in the inner closure that you might want. The only surprise is scoping - if you want to modify state you need to use a mutable data type because otherwise you'll be instantiating a private variable. But that hoop is easy to handle.

    def demo ():
        counter = [0]
        def increment ():
            counter[0] += 1
        def peek ():
            return counter[0]
        return (increment, peek)

    (increment1, peek1) = demo()
    (increment2, peek2) = demo()
    increment1()
    increment1()
    increment2()
    print peek1()
    print peek2()
So there. Function literals. They work.

But, you say, you really want anonymous classes? Well look up metaprogramming then. Python really has quite good support for it. There is no trouble creating anonymous classes on the fly with their own attributes, functions, and so on. They can even inherit from each other. http://www.voidspace.org.uk/python/articles/metaclasses.shtm... might be a good starting place on this for you.

(Note, I do not recommend metaprogramming unless the solution you make will be reused a lot.)

I've been heavily involved with python and javascript for most of my programming life and find them to be very similar. It's a joy to write in either language.
JavaScript also has much better scoping--Python's using = for both defining and setting variables makes life much more difficult.
This thread mostly contains superficial complaints (whitespace, self, the GIL) that are either explicit design decisions or not important for the kind of programming Python wants to address. Some more important problems that materially affect normal and sane use of Python:

- Broken scoping by default (the thread does raise this)

- Unicode is very painful in python2 (addressed very well by python3)

- Duck typing sometimes prevents early detection of genuine programming mistakes because of overuse: False + 1 == True

- No good isolation tools (virtualenv, the most common tool, silently fails to isolate dependencies when moved, which is obviously makes it tough to deploy using it)

- Poor packaging tools (only a few tools than they all have serious limitations such as not being able to package c-extensions).

- Some of the standard library is downright terrible. csv and robotsparser are good examples. This has the pernicious effect of widely-distributing libraries that have subtle but serious drawbacks.

> Poor packaging tools (only a few tools than they all have serious limitations such as not being able to package c-extensions).

Python stdlib will let you package a C extension. I am not sure why you think the opposite. http://docs.python.org/extending/index.html

> No good isolation tools (virtualenv, the most common tool, silently fails to isolate dependencies when moved)

If you mean it's not relocatable, there's a new option for this http://www.virtualenv.org/en/latest/index.html#making-enviro...

But being not relocatable is not really an issue, as you can simply re-run virtualenv in the new place. All libs you previously installed will work without having to install them again

> Some of the standard library is downright terrible. csv and robotsparser are good examples. This has the side effect of widely-distributing libraries that have subtle but serious drawbacks.

Some stuff in the stdlib are not good that's true, but we have a gigantic library ecosystem at pypi.python.org will very well written piece of libs. Using Python seriously, I have never ever felt the serious drawbacks you are talking about except with tarlib in python 2.4 which was seriously broken.

If you learn to like Python, you will learn to hate other languages. :)

The stdlib. It has some great parts and overall is just good enough (and desire to not break everyone's code) to not cause revolt and wholesale replacement.

FTPlib is atrocious.

httplib/urlib mess -> requests

os os.path, shutil subprocess is a ridiculous mish-mash of legacy, obscurity and surprising behavior. One example. os.mkdir (but only the leaf, and exception if it exists), want mkdir -p behavior. Is that an option to os.mkdir, fuck no! We need a whole new function for such dramatically different feature. Must be called mkdirs, fuck no! That would be too easy to remember and no one every look at our beautiful docs. os.makedirs is the obvious choice.

My biggest issue at this point is the implicit scoping. I've been using Python for 8 years (as well as a bunch of other languages, both for work and personally), and — while a lost cause, it won't be changed at this point — I've come to believe it was a Really Bad Idea[0].

Not only does it make bindings awkward (and sometimes broken, in different ways depending on the way "scope inference" is implemented) and tends to hide errors (e.g. typo) or generate them much later than possible (even though lexical checking is very cheap to perform at parse time, with explicit scopes), it has pretty much no actual benefit I can think of.

Especially in Python where assignment is a statement, not an expression, so it's not like explicit scoping would prevent putting assignments in place they're currently allowed.

[0] and it's one of the things I find utterly retarded in coffeescript.

"If you learn to like Python, you will learn to hate other languages."

I think it would be more accurate to say that if you learn other languages, you'll learn not to hate Python. Python is kind of mediocre in a lot of ways, but it's the only language without any deal breakers.

I can't tell if the last bit is being sarcastic on bad naming, or it's an oversight: the function you want is called os.makedirs http://docs.python.org/library/os.html#os.makedirs and has been around since 1.5.2.
I'd like to think/hope that no one would ever judge a language on it's FTP library =)
The scripting languages are all really more alike than different.

The main downside of Python compared to, Ruby, for example, is that Guido made some serious mistakes in the initial design and in the process of fixing them added a lot of extra complexity to the language. Python doesn't cleanly "fit in the head" the way Ruby or JavaScript do, at least for me.

But instead of wasting time micro-optimizing in such a narrow language space, pick Python or Ruby or whatever and spend your extra cycles on something different enough to be worthwhile like Go or Haskell.

> Python doesn't cleanly "fit in the head" the way Ruby or JavaScript do, at least for me.

I find the severe breakages and insanities of Javascript (such as tracking what `this` is) take much more brain-space than Python ever did, personally.

I learned python first, and I have the same complaint about ruby. When I was attempting to learn ruby, the subtle differences between blocks, procs, and proc.news, or whatever they are, seemed arbitrary and required too much thought to understand for my taste. In my brief exposure to ruby, that was symptomatic of a general trend in the language that there seemed to be many ways to accomplish a task, without a clear reason for the distinction. That's fine if you're writing code, but imo that's a feature that makes reading a language more difficult.
Did you learn python after you learned ruby or javascript? I have the exact same complaint about ruby not fitting in my head, and I think it's because I learned python first.
I endorse Go as a substitute for Python. Seriously! It may read like a spiritual successor to C, but in practice, with type inference, GC, and struct/map/slice literals, it's very (as the golang people put it) light on the page.
I think "scripting language" is not the fairest identification. But not for the reasons most people don't like it: quite the opposite! For me, the issue is not that you can use Python or JavaScript for general-purpose development--although, of course, you can--but that you can actually use Haskell for scripting. And it's actually very good at it, too!

I've been replacing my shell scripts with Haskell scrips lately and the transition is going well. Soon the only two languages I will ever need are Haskell and elisp!

> Python doesn't cleanly "fit in the head" the way Ruby or JavaScript do, at least for me.

I imagine the order on which you learn is important. I learned OOP with Smalltalk and C++ not only didn't fit in my head, it created an impressive allergic reaction. It took me 8 years to be able to get back to it and finally learn.

And it still feels a horrible kludge.

I learned Python before I had contact with Ruby and I find the irregular syntax hard to parse.

I also think the python 3 transition came at a bad time. There are a lot more strong alternatives to python now than there were when the transition was planned so putting up with the hassles of migration is enough for some people to consider how green the grass might be in another field.

Guido always said he could only afford to break python once but it's not clear to me he'll even get away with once.

"The scripting languages" is a very broad category. I think Python is rather different from Tcl, AppleScript, csh, JCL, MATLAB, and VBScript, to name but a few well-known scripting language. Ruby is definitely closer to Smalltalk (a non-scripting language) than it is to PHP (a server-side scripting language).

So I don't understand your comment about it being a narrow language space.

I have built an app of over 500k sloc in Python.

In retrospective, I feel the python as a language was a good choice, it helped us move very fast and do a lot of things :

- One good pythonner is very productive

- It was easier to get someone aboard, it is easy to get python and to reasonnably efficient with it.

- there are libraries for everything.

- going to cython or c++ was always an easy alternative for those crtical part of the code.

The only cases where python can be problematic are :

- high reliability code like trains or planes software, because python code is not provable.

- very high performance, where the slowness of python in the not critical part of code can be a problem.

Besides, It doesn't protect you against the classic problems of a big codebase built by a different of people over a period of time. Tools like pynocle or pylint were good for this.

So, in the end, python has obvious weakness. Most of the time It seems like a solid choice (among others). Right tools for the job, etc.

I never did understand why True and False are capitalized.

[EDIT: Turns out it's because all built-in constants are capitalized: http://stackoverflow.com/questions/521476/why-true-false-is-... . Learn something new every day. Still don't like it though.]

Also object-oriented programming in Python is very awkward. Then again, if I wanted OOP, I'd use C#.

I really like it's OO, it's regular and explicit. _ conventions are flexible for rapid development yet interfaces can still be hardened if required. You can do all sorts of stuff with decorators and Meta classes that you might do in macros in other languages but these are much more readable and predictable. The package system is simple and effective.
> Then again, if I wanted OOP, I'd use C#.

Which is not just reductionist, but downright silly. C# is not a very good OO language, in the same way Java isn't.

When I want OOP, I play with Smalltalk. Or Self.

"It's far from the metal"? No it isn't. It has ctypes, which is one of the best FFIs I've worked with. I wrote a trampoline-injecting kernel debugger in it. I don't love Python, but that answer disqualifies itself.
My biggest problem with Python is not that it's a bad language but that it isn't a great language. Why is this an issue? Simple: it's one of the most highly rated--and, frankly, overrated languages today. And, try as I may, I can never seem to get away from it: at least in my circles, it's even more endemic than Java!

I really wish people liked OCaml or Haskell that much instead.

For what python has been created for, there are really few if any drawbacks. This is still my go to language.

Something I wish python had a better support would be truly anonymous function I.e. you can't do:

  lambda x: raise "foo"
It's also very hard to write nested callback (Some pythonists like to argue that is actually a good thing).

Lastly, I wish the functional paradigm part of python was more consistent.

But all in all, I love python and I find it very hard to switch to something new without missing it.

While we are on the subject, I find that this answer provides with much better arguments - http://stackoverflow.com/a/431341

It's an interesting read - he begins with "The problem is that it is not as good as it is made out to be, in other words it suffers from a degree of hype. I'll try to argue this point."

Nobody has mentioned the inconsistent naming conventions in the standard library, which always drove me nuts.
- Multithreaded development; multiprocess is being favored (as well as event-driven) and there are some helpful modules for it

- Unicode (at least for Python 2)

- Debugging is a little behind other languages (pdb works)

- removal of map/filter in place of list comprehensions (they are certainly better but not faster)

Speed, definitely. Although in defence Ive always found python very easy to "hack".

Writing a C extension to do computationally intensive work is fairly simple.

With its versatility and extensability I once threw together a proof of concept password cracking cluster in a week. Redis for queues/data, MySQL for data, hashing code in a C extension, flask for the web interface. Cross platform and lovely :-)

Threading is the only real let down for me.

That thread is depressing - most of the things people are complaining about are conscious design decisions made by the python team. EG Complaining about self - explicit is better than implicit is a core property of python. I feel like `import this` would answer a lot of these.
I would say that Python has a feeling of inconsistency at times compared to other scripting languages. I don't mean this as a criticism. I like and use Python a lot for work and personal projects. Here's an example of what I mean by inconsistent:

len(a_string)

a_string.lower()

a_string.upper()

So here, there's a global, generic function len() that returns the length of the string while in the other examples, the string has methods such as .lower() .upper() etc. Why not have a_string.length()? I understand that generic functions are more efficient and even proper in OO. It just causes the feeling of inconsistency when you use the language a lot or when you are teaching a child how to program and have to explain the difference and why some things are methods while others are not.

Also, some python idioms (such as slicing) are not intuitive for many use cases. Here's an example of the traditional way in which to reverse a string in Python by slicing:

a_string[::-1]

In Ruby, you type a_string.reverse() and that is much more intuitive to a child when compared to the slicing in Python.

Having said all of that, I love Python and use it daily and encourage others to do so as well. I

My least favourite part of python (I'm overwhelmingly a fan, and it's probably my favourite language after Clojure) is the deliberately limited functional parts. Take list comprehensions, they work for simple things, but when you want to make it more complex, it wont let you break it over multiple lines, so you have to rewrite it into a for loop. Makes debugging awkward.
Did anyone mention the Gil? I'm hearing more and more complaints about that.
I was a Lisp/Scheme programmer. I use Python only because Norvig wrote that it isn't so bad. But I curse out loud every time I type in 'self'. I hate the lambda limitation (only expr). The scoping rules continue to confuse me. It's a good language if you're coming from C/Java. But it's a poor language if you're coming from Lisp/Smalltalk/ML.
I've written about this before here: http://news.ycombinator.com/item?id=3580590

Fundamentally, I believe Python's drawback is that it appears to draw heavily from the ABC history it has, and wasn't designed for power and flexibility.

I'd rather use Perl, Ruby or Lisp.

To this day I still hate the fact that wrong spacing causes a compiling error.
Performance and type safety which is true for any scripting language
self __init__ self.__init__ self self __init__ self
it doesn't wear a suit
Nice to see programmers.stackexchange.com being used for things like this. Hopefully it will put a rest to the same top comment on HN Stackoverflow stories complaining about how such questions are booted off Stackoverflow.com
Mutable default arguments. 'nuff said.