23 ms·
What are the drawbacks of Python?
- yen223 14y agoI 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-capitalized-in-python 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#.
- Wickk 14y agoHow do you find OOP in python awkward? Out of curiosity.
- yen223 14y agoAll those self statements.
- DeepDuh 14y agoWhat's even worse IMO is the lack of a proper built-in 'super'. The self parameters at least serve the purpose of deciding whether a function is a class function or object function. So yeah, I agree, python's OOP is kind of awkward. I love the ease of composition though, something I use extensively even in other languages since I know python.
- masklinn 14y ago> The self parameters at least serve the purpose of deciding whether a function is a class function or object function. No, it does not.
- eru 14y agoIt doesn't do that for the interpreter / compiler. But it's a common enough idiom that the human reader can rely on it.
- aptwebapps 14y agoTo elaborate on masklinn's answer, you need to add the @classmethod decorator to get a class method instead of an instance method.
- DeepDuh 14y agoNot the one you replied to, but one thing that hits me as awkward is the default static behavior of variables. something like class Foo: bar = 1 means that bar is now a static class member (static in Java's sense). It needs to be assigned to "1" explicitly in __init__ as far as I understand. That's just unintuitive and leads to lots of boilerplate, just so that you don't need specifiers like 'static'. Sometimes the fear of verbosity gets in the way of intuitiveness.
- rdtsc 14y ago> It needs to be assigned to "1" explicitly in __init__ as far as I understand. I don't think so. You do have to assign anything to it if you want to use it as a 'static' (actually 'class' attribute). You can access bar from Foo, as in Foo.bar or from an instance of Foo as in foo=Foo(); foo.bar. What probably is confusing to you is if you assign a value bar in an instance then that gets assigned to the instance not the class. That is if you do foo.bar=100 then now foo instance has an object attribute called bar=100 that overrides Foo.bar=1. But Foo.bar still stays at 1.
- masklinn 14y ago> Not the one you replied to, but one thing that hits me as awkward is the default static behavior of variables. There's no default anything, what you wrote sets "bar = 1" on the class itself, nothing more an nothing less, just as if you'd written: Foo = type("Foo", (object,), {'bar': 1}) (in fact that's pretty much what the class statement is sugar for) If you want to set it on the instance, set it on the instance. Python's class context is a namespace like every other, you can do any computation you wish in there, and at the end the ``class`` statements collects all bindings of the namespace and sets them on the class.
- rb2k_ 14y agoI always found it weird that they use len([1,2,3]) rather than [1,2,3].len (no, I don't want to call [0,1,3].__len__() . Why would I want to add all of those underscores.)
- griffindy 14y ago^ this ^ never understood why certain methods (or are they functions?) are not called on the objects. This is one of the reasons I love Ruby, everything is clearly an object.
- masklinn 14y ago> ^ this ^ never understood why certain methods (or are they functions?) are not called on the objects. Because they don't depend on a given class, they're protocols. There's no "master class" in which to put them, so they go in some sort of bastardized CLOS-like generic method instead.
- Flow 14y agoThere's no need for a super class to have a len() method. I don't get your reasoning here, Python is not a statically typed language.
- orangecat 14y agoWith duck typing, that shouldn't matter. Lots of methods in the Python standard library take "file-like objects" that have read() methods and no common superclass, and that works fine without read being a top-level function.
- rdtsc 14y agoIt is rather arbitrary yeah, but I don't mind it. Len kind of makes sense as a function.
- kami8845 14y agoreasoning by BDFL here: http://stackoverflow.com/a/237312/1188079 http://stackoverflow.com/a/237312/1188079
- nahname 14y agoAnother response from a different source. Having to include self as a method argument means that those are not methods, but static functions. This really means there isn't precisely methods at all and the whole OOP part of python appears hacked together. That part seriously turned me off when I encountered it. If there is a valid reason for this, it would go a long way in explaining away one of the major reasons I dislike python. Edit: Appears to be a bug and I cannot respond to your post 'masklinn'. Can you rework the example to include the result as 42 being an instance variable instead? Thanks.
- masklinn 14y ago> Another response from a different source. Having to include self as a method argument means that those are not methods, but static functions. This declaration makes no sense. > This really means there isn't precisely methods at all Of course there is: >>> class Foo(object): ... def bar(self): return 42 ... >>> type(Foo().bar) <type 'instancemethod'> >>> m = Foo().bar >>> m() 42 > If there is a valid reason for this, it would go a long way in explaining away one of the major reasons I dislike python. I don't know (and don't really care) if you'll consider it "a valid reason", but here's GvR's reasoning: http://neopythonic.blogspot.be/2008/10/why-explicit-self-has-to-stay.html http://neopythonic.blogspot.be/2008/10/why-explicit-self-has...
- jemfinch 14y agoFunctions don't magically become methods just because the language hid the "self" or "this" parameter. You're focusing on irrelevant details.
- nahname 14y agoIt's not that the language is hiding self/this so much as what manually passing those as variables represent. What you are saying is that you never need to call a method like this? > instance.method(instance)
- majormajor 14y ago
- calvinlough 14y agoThe code to call super is awkward. Instead of saying super(MyClass, self).foo(), I would rather just say super.foo(). Having to specify self or cls as the first argument of an instance or class method. This one is weird when you are learning Python because you don't pass in the first variable but it gets magically inserted for you. Creating a class method using a method decorator. Using a decorator to do something like this seems like a hack to me. Not having a clean way to specify what all the instance variables are outside of the constructor. People with a java background are used to putting instance variable declarations as the first thing inside a class definition. In Python, these will be static variables. This seems weird and inconsistent with the how method declarations work (methods only become class methods when a decorator is used). BTW, I like Python.
- masklinn 14y ago> The code to call super is awkward. Instead of saying super(MyClass, self).foo(), I would rather just say super.foo(). That's been changed in Python 3. Although it brings other issues. > Creating a class method using a method decorator. Using a decorator to do something like this seems like a hack to me. Why? Even more so, why is a decorator more of a hack than adding a new keyword (java) or special-casing method declaration (ruby) itself? Note that you can also create class methods without decorators if you wish to, by using a metaclass (I believe the method won't be accessible from the instance though) > This seems weird and inconsistent with the how method declarations work. It's actually very coherent: every binding created in the class scope is collected and set on the class object, as if passed as the third argument to `type`. That's it. Some objects (functions) are processed a bit more, but they still end up in the same place. > methods only become class methods when a decorator is used That's because the decorator is basically a flag to tell the attribute-resolution process to handle this method differently from the normal method-resolution process.
- regularfry 14y agoClass methods needing decorators really bugs me too. The problem goes back to explicit self. The explicit self, as currently implemented, carries no information: yes, you get to pick "self" as the instance name, but everyone picks "self" for that and There's One Way To Do It in Python anyway. If you could declare a class method like this: class Foo(object): def class_method(Foo): pass then suddenly explicit self gains a meaning (Hey! Instance method!) and class method declaration doesn't go through a completely unrelated mechanism. >> methods only become class methods when a decorator is used > That's because the decorator is basically a flag to tell the attribute-resolution process to handle this method differently from the normal method-resolution process. Do you see how that's just special-casing method declaration in a similar way to Ruby's mechanism, just relying on the programmer to drive the mechanism himself? To a not-so-casual observer it looks like Guido wasn't willing or able to change enough semantics to make a syntactic fix work for class method declaration, despite there being an obvious space in the syntax for it to fit in, so lent on a convenient implementation detail - a hack - to get the same effect with more work for the programmer. Of course, it's equally possible that he believes that class methods are a code smell and should be explicitly made ugly, which I could have a certain sympathy for, but to me the current situation just looks really inelegant.
- maglos 14y agoI 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.
- masklinn 14y ago> 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.
- eropple 14y ago> When I want OOP, I play with Smalltalk. Or Self. I'm reasonably sure there was an implicit "and be productive" in there. Smalltalk and Self are neat, but they don't do well on the get shit done test. (Yes, I know it is possible to get shit done in those. Compare the difficulty of getting-shit-done in them to an environment like Java or C#, and an unbiased source is going to have to admit they fail pretty hard if only because of stuff like Maven or, to a lesser extent, NuGet.)
- masklinn 14y ago> I'm reasonably sure there was an implicit "and be productive" in there. Right, let's move the goalposts and reduce the target, was there also the implicit assumption that the language should have a C-style syntax, be statically typed, run on a JITted runtime and be maintained by a big company?
- eropple 14y ago...or we can assume that the guy isn't an idiot and has selected C# as an object-oriented language for getting shit done. The only one who said "play" was you, and it makes sense because there's not really a lot of getting-shit-done using Smalltalk on modern systems. But he didn't say "play", he said "use", and a reasonable person might think that he said "use" because he has shit to get done. If hopping up and down and yelling about your pet likes when they don't really fit the topic is your bag, more power to you, but...
- masklinn 14y ago> ...or we can assume that the guy isn't an idiot No, I think we can exclude that one with no issue at all.
- hannibalhorn 14y agoNobody has mentioned the inconsistent naming conventions in the standard library, which always drove me nuts.
- ninetax 14y agoCould you give some examples?
- hannibalhorn 14y agoIt's not a secret at all, PEP 8 even acknowledges it - see http://www.python.org/dev/peps/pep-0008/#naming-conventions http://www.python.org/dev/peps/pep-0008/#naming-conventions - and of course attention to backwards compatibility is a good thing. - usually constants are capitalized, but math.pi and math.e aren't - the Decimal class has methods like is_nan(), and generally puts underscores in the method names, while the math package provides methods like isnan() - even within the same package, you have cases like itertools.groupby() and itertools.combinations_with_replacement() Not a deal breaker, it's just a drag when you only work in a language once every few months, and you constantly have to look at the docs to know whether something is alllowercase, ALLCAPS, camelCased, with_underscores, etc.
- tocomment 14y agoDid anyone mention the Gil? I'm hearing more and more complaints about that.
- yen223 14y agoHaving worked with multi-threaded applications in other languages, I'm starting to think that the GIL is more a good thing than a bad thing. Seriously, threads are evil.
- w0utert 14y agoThe GIL does not make threads less evil than you apparently already find them, it just makes them a lot less useful. Threads in Python still have all the pitfalls and complications they have in other languages, it's just that they cannot use multiple cores or hardware threads. So you get all the evil bits (race conditions, deadlocks, having to protect access to shared state, etc), but you miss out on all the performance benefits threads can have on parallel hardware. In Python, threads are only useful as an abstraction of things that have to run concurrently, even though they never do.
- masklinn 14y agoNot that I want to distract of your righteous rant, but threads also work without issues when doing mostly IO: C libraries and implementations are free to release the GIL (and often do). So if you want to e.g. fetch a bunch of things concurrently, those will be done concurrently. And your > have to run concurrently, even though they never do. is way off base. Likewise, if you're doing CPU-heavy crunching (likely implemented in C or Cython), you can release the GIL and let the interpreter run some other bytecode at the same time.
- gizmo686 14y ago> In Python, threads are only useful as an abstraction of things that have to run concurrently, even though they never do. This is just false. Threads still offer performance benefits for non-CPU bound operations. For example, if you are trying to download data from 100 different sources, you could do it in a single thread, but python would spend most of its time idling while other prosseses do work, or you could have 100 threads, so python can do work while it is waiting on other stuff to get done.
- raverbashing 14y ago- 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)
- masklinn 14y ago> - Debugging is a little behind other languages (pdb works) So do the numerous extensions/replacements for pdb, or the multiple graphical debuggers (e.g. PyCharm's, PyDev's, PuDB, WinPDB, Kodomo IDE's, Wing's, ...). Python doesn't have a time-traveling debugger à la OCaml, but that's about it as far as I can tell. > removal of map/filter in place of list comprehensions (they are certainly better but not faster) What are you talking about exactly? Because I find two possible interpretations of that phrase, and neither comes close to being correct.
- raverbashing 14y agoWell, my mistake, map and filter are not faster than a list comprehension (at least not in 2.7) My test case is: f = [x^2 for x in l if (x % 2) == 0] (and something similar with map and filter) (where you read x^2 please consider x(double asterisk)2) For 500k elements - xrange(500000) - this takes: 0.122527122498 (list comprehension) 0.145442008972 (map/filter)
- denzil_correa 14y agoAn up vote just for Unicode in Python 2. It kills my life big time.
- emidln 14y agomap and filter still exist. reduce was demoted into the stdlib instead of being builtin in 3.x. list comprehensions generalize to other types (generator expressions (aka "lazy sequences"), set comprehensions, dict compresions) Compare this syntax (using dict comprehensions in 2.7): {k:v for k, v in something.iteritems() if v == 3} to this syntax using map/filter: dict(filter(None, filter(lambda x: x if x[1] == 3 else None, something.iteritems())) More frustrating to me is that there isn't an imap/ifilter builtin (I understand that it's in stdlib, I'm just lazy).
- lazydon 14y agoWhile we are on the subject, I find that this answer provides with much better arguments - http://stackoverflow.com/a/431341 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."
- nahname 14y agoMostly it is the age old complaint, can't build something big in a dynamic language. The evidence is that I don't know of anything big in a dynamic language. Not exactly great points against python when the argument boils down to, "all dynamic languages are bad."
- d0m 14y agoFor 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.
- cageface 14y agoThe 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.
- cageface 14y agoI 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.
- masklinn 14y ago> 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.
- VeejayRampay 14y agoThat "this" business is absolutely ridiculous. The fact that Javascript remains the SOLE language to script browsers in 2012 really really pisses me off. It is not a very good language in terms of design (even though it's been proved to be quite efficient and capable in the past few years).
- lost-theory 14y agoDid 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.
- kanja 14y agoThat 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.
- orangecat 14y agoPracticality beats purity. Python should support better function literals for the same reason that it supports the "implicit" [1,2,3] instead of making you explicitly create a list and call append. I'd say self falls into the same category, although I haven't found it as much an annoyance as some.
- ErrantX 14y agoSpeed, 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.
- masklinn 14y ago> Writing a C extension to do computationally intensive work is fairly simple. Even more so with Cython, which does most of the hard work for you.
- Xixi 14y agoOr the recent numba: https://github.com/numba/numba https://github.com/numba/numba
- njharman 14y agoThere's so many solutions to the "speed" argument I don't even see it as an issue. - C-extentions (many std and 3rd party libs that need speed are written in C) - numpy http://numpy.scipy.org/ - numba https://github.com/numba/numba - cython http://www.cython.org/ - pyrex http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ - http://psyco.sourceforge.net/ -> PyPy (some day...)
- SoftwareMaven 14y agoWhere you were already using external queues, threads shouldn't have been an issue: just have multiple processes going (one for each core). Or use the processing package if you want more "threadlike" control. It is unfortunate that you have to know that kind of thing a priori. "Oh, look, a nice, built-in threading module." Yes, BUT... EDIT: I just re-read the way you wrote the "threading" comment and realized you probably weren't talking about it in the same context. Amazing what a word or two can do to understanding.
- recoiledsnake 14y agoNice 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
- njharman 14y agoIf 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.
- masklinn 14y agoMy 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.
- emidln 14y agoassignment is a statement if you want it to be, but you can generally use setattr() as well. E.g. modifying global scope as an expression: import sys module = sys.modules[__name__] def foo(k,v): setattr(module, k, v) foo('spam','eggs') assert(spam == 'eggs')
- masklinn 14y agoThat only "works" for the global scope, or by chance in some cases in the local scope if you do a star-import within the local scope (yeah…) I don't consider that working, it's a piling up of hacks. Which is great when you need them and they work, but... Also, there's a simpler way to implement your snippet: globals().__setitem__('spam','eggs')
- rjh29 14y agoMy favourite critique of Python: http://www.quora.com/What-are-the-main-weaknesses-of-Python-as-a-programming-language http://www.quora.com/What-are-the-main-weaknesses-of-Python-...
- lectrick 14y agoself __init__ self.__init__ self self __init__ self
- lani 14y agoit doesn't wear a suit
- topherjaynes 14y agoIs this a quote from somewhere? I laughed, and now want to make a opensource project suitupy
- calpaterson 14y agoThis 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.
- tarekziade2 14y ago> 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 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-environments-relocatable 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.
- calpaterson 14y ago
- cdavid 14y agoQuite 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.
- theorique 14y agoIn 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.
- dkarl 14y agoWhat 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.
- eru 14y ago
- tubbo 14y agoIt is kinda slow, making it a little hard to make full graphical apps with a scripting language like Python (or Ruby, for that matter). Why are all scripting languages "interpreted" rather than compiled, by the way? Is it not possible to create a dynamic language as powerful as Ruby that's also interpreted?
- LBarret 14y agoI 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.
- orangecat 14y agoPython 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.
- whalesalad 14y agoI'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.
- tikhonj 14y agoJavaScript also has much better scoping--Python's using = for both defining and setting variables makes life much more difficult.
- masklinn 14y ago> JavaScript also has much better scoping Though I generally agree, that's as long as you mandate linting. JS's implicit globals are even worse than Python's implicit scoping.
- tikhonj 14y agoThat's fair. My editor marks those for me automatically, so they're much less of an issue for me, but they are still really stupid. On the other hand, you can work around that particularly stupidity just by being careful. Working around the Python limitations requires either something hacky like using a one-element list instead of a variable or (only in 3, I think) a rather ugly "nonlocal" statement at the top of your scope.
- hiddenbayes 14y agoAdding a "var" keyword, similar to that of Javascript, was discussed on the Python mailing list a while ago. See here: http://mail.python.org/pipermail/python-3000/2006-October/003968.html http://mail.python.org/pipermail/python-3000/2006-October/00...
- pbiggar 14y agoMy 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.
- masklinn 14y ago> it wont let you break it over multiple lines ? result = [ (value, process(value), process(key, value)) for key in generator for value in generate(key) if some_condition(key) if other_condition(value) ] or did you mean something completely different? Maybe the problem of not being able to use statements in comprehensions (or lambdas)?
- pbiggar 14y agoRight, I meant using statements, sorry. It's been quite a few months since I wrote python, so I think I've forgotten most of the details.
- Daniel_Newby 14y agoJust define a nested function above and call it in the list comprehension.
- pbiggar 14y agoSame problem - I have to rewrite my lovely list comprehension instead of just adding a statement to the body.
- tptacek 14y ago"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.
- _dps 14y agoYou're probably aware of LuaJIT (http://http://luajit.org/ http://http://luajit.org/) already but I'll toss it in for other readers: as a former heavy user of ctypes, after discovering LuaJIT and its FFI I haven't touched ctypes again. For people who need to do this kind of work, it's worth looking into (enough so that one of the core PyPy developers is emulating LuaJIT's FFI design in the project Python CFFI http://cffi.readthedocs.org/en/latest/index.html http://cffi.readthedocs.org/en/latest/index.html).
- Sukotto 14y agoI don't know what trampoline-injecting means and my googlefu has failed me. Would you briefly explain what you mean?
- tptacek 14y agoInstead of implementing breakpoints with INT 3, which relies on the OS's debug event support, our debugger injected new basic blocks into the program to pause the target, perform I/O with it, and redirect it to other code paths. You should have no trouble looking up what a "trampoline" is, but I'm abusing the term a bit.
- gruseom 14y agoSo you made a debugger below the OS by instrumenting the target program to do debuggery things? That's pretty cool. But at what granularity did you inject the code? Presumably not around every single instruction. But if it was just on demand wherever the user set a breakpoint, how would you implement stepping?
- 14y ago
- tikhonj 14y agoMy 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.
- snogglethorpe 14y agoYeah. Python has an awful lot of warts, considering the way so many people fawn over it. Really the main strength of Python is not the language at all, but the huge number of libraries written for it, and the wealth of tools and "community." Fair enough, it was in the right place, at the right time, but if history is going to throw its weight behind something, it is a little annoying when that thing is rather mediocre...
- pnathan 14y agoI've written about this before here: http://news.ycombinator.com/item?id=3580590 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.
- monochromatic 14y agoMutable default arguments. 'nuff said.
- gizmo686 14y agoIronically, the one time where I noticed this bug was while testing a component, whose only use involved me emulating the behavior of mutable default arguments on a higher level. I still think it is a horrible system. My strong opinion on it might be because I spent hours looking at our c-extensions for the source, because the previous two 'language bugs' I ran into were both in our c-extensions, where we had a type that could not cast to it self, and someone thought it was a good idea to make ~x mean x-1.
- anuraj 14y agoPerformance and type safety which is true for any scripting language
- 16s 14y agoI 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
- silverlake 14y agoI 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.
- DonnyV 14y agoTo this day I still hate the fact that wrong spacing causes a compiling error.