8 ms·
A short list of things I don’t like about Python
- deleted 17y ago[deleted]
- daeken 17y agoAgreed on every point, but I have to add a few things. - No real metaprogramming is a big problem for me. I want decorators to be able to manipulate the AST (I'm playing around with a way to do this: http://pastie.org/490836 http://pastie.org/490836 ) at the very least, and preferably real macros that can add new syntax. - Anonymous functions. I want real anonymous functions in Python, not lambda or anything like it. After a long time of hacking Nemerle code, I go back to Python and cry when I write lambdas. - Tail call recursion. Another functional programming thing that I'd absolutely love to see, just because it's so incredibly useful. Sadly, I know none of these will likely be implemented, as they're just not the Python way, but it doesn't change the fact that I love Python and would love to see these changes.
- jnoller 17y agoYou see, if I were someone else, I might have pointed out all three points you list here, except I don't like all three of them :) I can see the argument for tail recursion - except that people who really love tail recursion seem to over use it (all good things in moderation). Still, I might like to see it in core; as for the other two, well - I don't even like lambdas, even as implemented in python (I think it might be a taste thing) and metaprogramming in the wrong hands is painful at best.
- gchpaco 17y agoPython as a language is so good that it becomes difficult to concisely describe why one wants metaprogramming. Generally speaking the reason one wants metaprogramming is to make the language of the domain you are thinking in and the language of the program as close as possible. So in banking we talk of accounts and transactions, not rows in a database. The need for this is so acute in Java it makes my teeth ache. Python is much more flexible; so much so that this becomes a difficult to explain urge, but it is still there. An example may be worthwhile. Consider SCons. Know anybody who uses it? There were a number of issues going on there (one of which was the general lameness of the Cons infrastructure--I'm sorry, I use the fact that make is a dependency computation engine, all the damned time, and ant and Cons and every other lame-ass "make replacement" that doesn't do this drives me up the wall) but IMHO the decision to make the syntax raw, executable Python code did not help. Now, granted, I consider myself a Lisp hacker, so maybe you'll just write this off entirely. But the key thing I have with Python, the key complaint I have, is that there are fundamental domain assumptions baked into the language that are sometimes appropriate (numpy is an enormous success, for example) and sometimes aren't (SCons, HTML template system du jour, configuration files, etc.), and I can't change them. Edit: an example came to me as I thought about this. So how's this as an explanation: in Java and Python, you can have as many nouns as you want. You can have as many verbs as you like. Adverbs are hard. Pronouns are almost impossible. And syntax? Forget it. It makes for an interesting contrast with mathematical notation, which takes time to learn and is inconsistent and only governed by social constraints but, at its best, is so good at communicating information that it fades into the background, just as = or 0 do.
- jnoller 17y ago"Now, granted, I consider myself a Lisp hacker, so maybe you'll just write this off entirely." Now why would I write you off? :) I would like to see examples of what you're talking about however.
- gchpaco 17y agoIt's hard to quantify the benefits of system-qua-language without pointing you at Maxima or something (a computer algebra system well integrated with the underlying programming language). But here's a small example of the sort of thing I want to do with metaprogramming in Python. In C, C++, Java, and almost every commonly used language, parsing is usually done by writing a parser in a different language (yacc, ANTLR, whatever) which is then compiled to source code which is then compiled again. In a language with good metaprogramming facilities, the parser is written in the language; macros in Lisp-descendants, parser combinators in Haskell (itself probably about as flexible syntactically as you can get without actually having macros), whatever the hell Forth people call it, etc. This has, at least in theory (a lot of parser combinators in Haskell are impossibly naive, but that's an implementation detail or so I claim), no demerits over the C approach, but it integrates better with the language. This is not just a difference in taste, either. As a different example, Python had the problem wherein regexp strings were getting impossibly difficult to write. They added raw strings to the language to get around this. Schemers had the same problem, but one of them (Shivers) wrote a regexp language with escapes to the underlying Scheme implementation that compiled to regexps but made it possible to read them like they were any other kind of code, instead of weird terse utterances. You can still do the weird terse utterances if you like, but you can also write regexps like they were any other kind of Scheme code. When I was doing web programming in 2000, I hacked an SQL generation library in Python. It felt awkward to use and was verbose but I deemed it better than being paranoid about SQL injection attacks. If I had good metaprogramming facilities, I might have been able to implement the database comprehensions they have in C# now (the LINQ facilities). I probably wouldn't have decided to do so, because even in 2000 I had some taste, but I could have and experienced all the benefits the C# people claim to have. Another thing that came up during that same project was that I was trying to do what we now call continuation-based web frameworks in a language with no explicit continuation apparatus. This is similar to what PG described doing in Viaweb, but I didn't have a metaprogramming setup to help me out with it. I did the CPS conversion manually, and lemme tell you it was a royal pain in the arse and contributed significantly to the difficulty in implementing that setup. If I had good metaprogramming frameworks I could CPS convert the code automatically, as PG did. Would you like more? :)
- jamongkad 17y agoYou're right what you've just outline are features that the community as a whole show so much aversion to. I guess they believe functional programming does not help with code readability. But I do hope that Python's metaprogramming features get more attention and multi-line lambdas would be nice but not necessary. I can live without TCO as well.
- jnoller 17y agoYes, I suspect you would find that many within the community do find functional programming constructs do not assist in readability of the code. That group would also include me, while I might use some FP things every so often, I tend to shy away from them for that express reason.
- ubernostrum 17y agoMeanwhile I simply shy away from the idea that the things I do in my code can be so neatly classified :)
- tmoertel 17y ago> I guess they believe functional programming does not help with code readability. What does that statement say more about, the Python community or the readability of functional programming?
- jamongkad 17y agoI think it's a little bit of both. Functional style in languages such as Scheme, Lisp and the like tend to nest functions. Which makes readability a bit hard, which goes against the design goal of Python in the first place.
- tmoertel 17y ago> Functional style in languages such as Scheme, Lisp and the like tend to nest functions. Which makes readability a bit hard, ... Hard for whom? People unskilled in functional programming? People skilled only in the English language find Greek "a bit hard", too. This truth is so well established that it forms the heart of a colloquial expression, one used to confess a speaker's inability to understand a subject in general: "It's all Greek to me!" And yet I trust that you haven't fallen into the trap of thinking that this expression, no matter how much it is repeated by English-language speakers, reflects poorly on the Greek language, itself. The ancient Greeks, after all, didn't seem to have any difficulty using their language to great effect, and with remarkable clarity.
- silentbicycle 17y agoLua is very similar to Python (with more Javascript and Scheme, perhaps), but with real lambdas and tail calls. It's a different language with different trade-offs (it's standard library is tiny; embedding is its primary niche), but its dev team very much shares Guido's sentiment of "keep it simple and don't clutter the core language trying to make it everything to everyone". If you want to see the parallel evolution of language with very similar values but a slightly different set of features, it's a good one to check out.
- stcredzero 17y agoLua is also impressively fast!
- silentbicycle 17y agoI think Lua's biggest assets are how easily it can be used with C (which is where a lot of the speed comes from), and how incredibly portable it is. The language is freaking tiny, it will run on anything with a C compiler, and it usually builds in just a few seconds. While it doesn't have a huge standard library, there are tons of C libraries, and writing Lua wrappers for them is dead easy. Also, LPEG (http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html) rules. Edit: That's what I meant, that you can move code over to C. That Lua itself is faster than the other major scripting languages is just a nice perk. :) (Also, there's LuaJIT, but only on i386.)
- davidw 17y ago> easily it can be used with C (which is where a lot of the speed comes from) I don't think the two are necessarily related: Tcl has a great C API, but is middle of the pack in terms of its own speed. Of course a good C API is an essential 'out' for scripting languages, so that you can write stuff in C where needed. Indeed, the idea behind Tcl was to not care much about Tcl's speed, because performance critical stuff would be done in C anyway.
- jnoller 17y ago
- stcredzero 17y agoI want decorators to be able to manipulate the AST I've thought of a way to do this in Smalltalk. http://news.ycombinator.com/item?id=622773 http://news.ycombinator.com/item?id=622773 Using #perform: style calls as decorators is ugly, though. Instead of that, one could utilize a MethodWrapper instead. http://www.refactory.com/Software/MethodWrappers/ http://www.refactory.com/Software/MethodWrappers/ But instead of executing code before & after the method, you'd be executing an alternative version of it instead.
- ubernostrum 17y agoI can't help thinking that certain languages impose their own variation of the Blub syndrome, namely in leading to the conclusion that one particular way of thinking about programming should be the One True Way to think about programming. Various Lisps, for example, produce the well-known "when all you have is an AST, everything looks like a macro" syndrome; Scheme inculcates a desire to use tail recursion even when counting on one's fingers; etc. This is, incidentally, precisely the same criticism proponents of functional programming typically level at proponents of, say, object-oriented programming. And I've no doubt that, if the popularities of those paradigms were reversed, comments like this one would be the usual snipe from OOP fans at their "unenlightened" functional brethren and sistren. At any rate, I'm very far from being convinced that this is a healthy thing for either the programmers affected, or for the state of the art in general.
- halo 17y agoOn the other hand, you get complaints over the complexity of C++ because it doesn't really have 'One True Way' to do anything. Ultimately, it's a case of trade-offs, and accepting that can't win them all.
- j_baker 17y agoI agree 100%. While I would like to see macros, I think they're more in the "That would be so cool!" category than the "This is really necessary" category.
- rw 17y agoWhen you can modify the semantics of the entire language, you can use any paradigm you want.
- sethg 17y ago...which is great, until you want to use one paradigm and you also want to take advantage of a certain library, and you discover that the library uses a completely different paradigm. Either you put up with an impedence mismatch between your code and the library, or you discover that in this language all paradigms are equal but some are more equal than others.
- tsuraan 17y agoThe author makes the assertion that flat is better than nested, and indeed it's one of the rules in "import this", but I just don't see it. I spend about half my time in python, and about half in erlang. Erlang makes python look pretty deeply nested, since it pretty much lacks support for any namespace nesting, but honestly, I prefer Java's namespaces. If I were to write a library in Java (god forbid), I'd start it in net.tsuraan.whatever. I'd know that I'm not going to have namespace clashes with the standard library, apache, nor anybody else that is half-way sane. In python, the root namespace is pretty crowded, and you need to step carefully to avoid namespace clashes. In erlang, it's even harder. Why do people like flat namespaces, as opposed to reasonably nested ones?
- jnoller 17y agonoooo, I wasn't making that assertion - I was saying the argument against my gripe about nesting bits of the stdlib deeper would be responded with "flat is better than nested". The "flat" crowd always whips that one out when someone suggests nesting it a bit more. I am a fan of nesting it just a little bit deeper than what it is today.
- tsuraan 17y agoIt reads as though you generally do agree with the flat is better than nested though; your argument appears to be more against how the system is currently organized, rather than being concerned with the ability to write libraries without worrying much about namespace clashes. I'd love to see the entire python standard library moved into a root-level "python" namespace; I'm guessing that would be about as popular as curly braces with the general python crowd... Heck, even the ability to root your imports, like import .email would bring in the root-level email library, would be pretty nice. I'm sure I've seen the idea shot down before, but I can't recall what the reasoning was.
- jnoller 17y agoRelative imports are in python, which allows you to dictate where a "foo" module is imported from
- T_S_ 17y agoHe forgot one: "Everything is a run-time error."
- jerf 17y agoSomebody stopped reading before 5 and 6.
- mgreenbe 17y agoIncorrect. Consider a file test.py: print "hello" x = 1 + Note the syntax error. Running it, we see: $ python test.py File "test.py", line 2 x = 1 + ^ SyntaxError: invalid syntax If syntax errors were runtime errors, we would see the effect of the print statement. This is not a top-level effect: the same is true even if a syntax error is under a function.
- zmimon 17y agoYay for another person like me who wants to be able to sprinkle just a little static-typing goodness back into the dynamic typing orgy everyone is having these days. I don't mean huge cumbersone Java or C++-esque typing, just the simple ability to declare to the compiler (or to humans trying to read my code) - 'object foo is a Foo, please give me a hand and tell me if you can deterministically figure out that it is not, or if it is doing something that Foos are never allowed to do'.
- silentbicycle 17y agoWhile it's not caught at compile time, why not use assert? assert(type(x == "float")) should be a very clear declaration to others reading the code, and assert is also not limited to type checking. I like static typing in some circumstances, but adding it to Python would be a major change to the language. I'd rather just use OCaml when static typing is really important, and save scripting languages for the niches in which they excel.
- jnoller 17y agoasserts are stripped out when python is run in optimized mode. Not to mention sprinkling them around your code is infuriating for people dealing with your code :) I'd also point you to the links to guido's writeup I put in the post, I agree: it changes the language too much to be a positive net gain.
- silentbicycle 17y ago> sprinkling them around your code is infuriating for people dealing with your code Would this necessarily be any less true of static type annotations, though? And as for them being stripped out, yes - it's for making debugging easier, not performance.
- tow21 17y agoMacros. Macros macros macros. Even if I can't have full-on lisp-y AST macros, I'd kill for relatively simple CPP-ish textual macros, just to cut down on boilerplate code. Not that the chances are any good, and I can understand why - it would be decidedly un-Pythonic. But it's just mildly frustrating at times when I find myself writing the same coupe of lines of code twenty times within a file, because scoping rules insist they have to be there (reading from locals() is often where it hits me))
- deleted 17y ago[deleted]
- j_baker 17y ago"I'd kill for relatively simple CPP-ish textual macros, just to cut down on boilerplate code." If you're getting enough boilerplate writing Python to want something horrendously evil like C++ macros, you're doing something wrong. Not that there isn't a valid argument for macros for Python in general. To be clear though, Guido has said that he'd be open to the concept of Macros if someone were to come up with a good proposal for them. As far as I know, no one has stepped up the plate though.
- euccastro 17y agoI have used exec and eval as something way better than relatively simple CPP-ish textual macros. What's better, you have all the power of Python string manipulation. If you're reading from locals() a lot you're in evil land anyway. :)
- j_baker 17y agoexec and eval can be powerful. But that's their problem. They're a little bit too powerful.
- adw 17y agoThis is a pretty minor thing compared to a lot of the warts here - to be honest, I'm not in the league of most of you as a programmer, I suspect - but two pretty simple things I've found surprising/annoying and have managed to shoot myself in the foot with: * loops leaking their control variables: I get why this is useful sometimes, but it particularly bites with list comprehensions, especially as generator expressions don't leak. Apparently the list-comprehension part of this goes away in Python 3 (http://mail.python.org/pipermail/python-3000/2008-April/013189.html http://mail.python.org/pipermail/python-3000/2008-April/0131...). * How mutable default argument values behave. Now, this one's even mentioned in the tutorial - http://docs.python.org/tutorial/controlflow.html#default-argument-values http://docs.python.org/tutorial/controlflow.html#default-arg... - so I've really got no excuse, but that hasn't stopped me getting it wrong before!
- jnoller 17y agoMutable arguments are considered harmful; and will probably cause cancer, plague, locusts and other end-of-the-world problems.
- j_baker 17y agoI was under the impression that Python's handling of mutable arguments was actually a feature. Although I must admit, I've never written any code that would use it.
- adw 17y agoYeah, that's more or less what happens. What you'd, admittedly naively, want, though, is a way of saying "a new empty dictionary, please", so you don't wind up having to write this kind of thing: def f(a, d=None): if d is None: d = {} which, okay, it's a minor deal, and I know why it happens, but it's the kind of thing I forget you need to do!
- j_baker 17y agoMan, I was ready to reply with a nasty comment until I saw who the blog post was from. :-)
- jnoller 17y agoHeh. No reason to flame me ;)
- rbanffy 17y agoI think this whole "things I hate in $language" misses a very important point. There is an immensely rich universe of languages you can chose from today. If you want Lisp-ish lambdas and macros, you should, by all means, go with Lisp. If you want to build your own DSL, you may as well chose Ruby. If you want pythonic indentation-as-structure, you should go with Python and, if you love the "do this if that" thing, you should consider Perl. Having said that, I would love if Python threads had better support for multi-processors. It's not like changing syntax and turning Python into something it isn't, it's just properly implementing something that should be there from day 1.
- jnoller 17y agoI don't think it misses anything. My post is mainly around things I want to make better, to make python better. I am definitely a fan of using the right tool for the right job: that means using the language which fits the domain. This is why I don't think arguments for "more functional programming" features or "be erlang" hold a lot of water for Python; if that's what you want, you need to go use those tools.
- rbanffy 17y agoI agree with your points and, having done a lot of Zope/Plone programming in the past, your #1 is by far my #1 too. More than once I have sworn if I knew enough of the inner workings of CPython, I would solve the problem myself, even if it took years of labor, even if I had to rewrite each and every module out there ;-) I think my rather inadequately thought out response was because most of the comments here in HN were about changing Python into something else. I am truly sorry I implied your article was about turning Python into something unnatural and I most certainly owe you an apology.
- jnoller 17y agoIt's nothing. But I wholly agree that many of the comments here and elsewhere are very much in the vein of "man wouldn't it be great if python was OCaml?!!", which is about as useful a comment as a hole in my head.