Python is a joke. Semantically, you're put in a straightjacket1 (thanks, Guido!), and tuning for performance is impossible2.
Either use a powerful high-level language (Common Lisp) or go to back to C. You might say, "but I'll mess things up in C." But this is exactly the point! If we remove all of the lame languages that let total failures write code, they will have nowhere to go, and the Order will be restored once again.
In general, remember that when you use a language above native machine instructions3, you're accepting the abstractions and philosophies of the people who created that language. If you have to use something that's broken or backwards just to stay afloat (or worse, you don't realize that it's broken or backwards), something is wrong with you.
1 Before you tell me that "it supports functional, LOL!": no, it doesn't. Obviously, very few people can define "functional" precisely, but if you take 10 minutes to do a little Googling, you'll find that the functional features of Python were crippled from the start, and Guido has expressed specific dislike of even those. It seems like Guido would prefer to make his language "idiot friendly", rather than powerful, in order to get a large number of people using it. It's not just functional programming either. Everything in Python reeks of the "one correct way to do it", to the point where doing anything complicated feels tedious.
2 Obviously, a better data structure or algorithm will always help, and often people who complain about performance don't know what they're doing. However, doing anything beyond that in Python is basically impossible, save for some of the projects like Psyco (which sort of work sometimes, but not really), or writing your core functions in C and then interacting with them in Python. The last time I tried the latter, it was downright fugly. Contrast this with Common Lisp (SBCL), and a person has a valid reason to find the state of Python unacceptable.
3 I realize that you can "pick" different architectures, and could theoretically create your own. But since the former is limited to a handful of choices, and the latter basically never happens, I decided machine instructions were a fair choice for the "unmovable bottom" of the hierarchy.
>>10
You call Python limited then suggest Lithp as a solution? Unless you're building something like the ``In Lisp'' DSL on top of your favourite flavour of Lisp, you are full of shit and I hate you with every fibre of my being.
I tried it once. I liked the features and "feel" of the language more than Python, but speed was still a huge problem (not sure what it's like now, but I somehow suspect Ruby is still slow). I remember the metaprogramming feature being really lame compared to Lisp, although I'll admit that I rarely use macros in Common Lisp, so I won't count that against it.
The community, however, is absolutely intolerable (and I say that with a full understanding of the Common Lisp community). As Rails gained popularity, it seemed (at least superficially) that most of the people involved with Ruby were doing it for the sake of Rails, and I figured (and was later vindicated by my guess being correct) that since Rails was another fluffy, vapid fad that would die out (Rails has already lost most of its sex appeal among the Macbook/Radiohead/iPod/Textmate/Starbuck's crowd), the conflation of Rails and Ruby would ultimately hurt Ruby.
Still, if I had to choose between Python and Ruby, I'd probably take Ruby. However, I still see no reason to use it over Common Lisp. In general, I've found languages like Python, Perl and Ruby to be easy to use, but I always end up replacing or rewriting everything I do in those languages anyway. Thus, I've been getting by using less "scripty" languages, and I haven't regretted it once, even if it means the initial development process is a little bit slower.
>>20 Exactly how am I full of shit? You are only full of shit if you are suggesting the use of CL, as-is, as a replacement for, say, Python.
How is Common Lisp more limited than Python? It isn't. Both of them have limited syntax. At least in CL, you can do away with most semantic limitations by using the language's built-in macro abilities -- however, the syntax problem remains. Python has good-enough syntax most of the time, but when it does itch, you can't just scratch it yourself, which is extremely annoying (at least to me). I've done a bit of Lisping and I do admit that I sometimes find myself missing various features from Lisp in other languages, such as its lists and recursion-centredness. Lisp semantics are beautiful, but the syntax leaves a lot to be desired. And no, macros can't fix the ((parens)). No, I don't want to use a special plugin for a special IDE. No, I don't want to wait until an optical illusion (or a visual cortex malfunction) makes them disappear. Yes, I want operator precedence. Yes, I want operators. No, I don't want one for everything. Might as well write my own language or die trying -- it's not like I'm going to convince van Rossum (or any other BDFL) to fix their stupid shit.
Writing this post made me sad and angry so I'm going to get drunk. Later.
You're primarily pissed off about syntax. While I think semantics are usually more important, syntax can be enough to turn people off from a language and shouldn't be ignored. I'm sorry that the parens have turned you off to Common Lisp.
You could write your own language, although I would evaluate existing options first. You might complain that very few people use the language and write libraries for it, but the chances that people are going to do it for your language are even worse. That being said, good luck.
Lisp
digit X:{\0;\1;\2;\3;\4;\5;\6;\7;\8;\9} -> X,asInt-(\0),asInt
number [@Xs] -> {N [X:!digit @Xs] -> r 10N+X Xs; N [] -> N} 0 Xs
op [X:{\+; \-; \*; \/}]->X,asSym
term [\( A:@expr \)]->[A]; [A:@number]->A
expr [A:@term O:@op B:@expr]->[O A B]; [A:@term]->A
parse X -> strip \Space X,asList | expr
Python
def getExpr(ss):
global curr_tok,curr_val,s,curr_err
def getToken():
global curr_tok,curr_val,s,curr_err
s=s.lstrip()
if s=='':
#curr_tok='end'
return
c=s[0]
j=1
if c=='+':
curr_tok='plus'
elif c=='-':
curr_tok='minus'
elif c=='*':
curr_tok='mul'
elif c=='/':
curr_tok='div'
elif c=='(':
curr_tok='lp'
elif c==')':
curr_tok='rp'
elif s[0].isdigit():
for j in range(len(s)):
if not (s[j].isdigit() or s[j]=='.'):# or s[j].lower()=='e' or s[j]=='+' or s[j]=='-'):
break
curr_val=float(s[:j])
curr_tok='num'
else:
#curr_tok='err'
curr_err=(1,'bad token')
j=0
s=s[j:]
def Expr1():
global curr_tok,curr_val,s,curr_err
left=Expr2()
while 1:
if curr_tok=='plus':
getToken()
left+=Expr2()
elif curr_tok=='minus':
getToken()
left-=Expr2()
else:
return left
def Expr2():
global curr_tok,curr_val,s,curr_err
left=Expr3()
while 1:
if curr_tok=='mul':
getToken()
left*=Expr3()
elif curr_tok=='div':
getToken()
d=Expr3()
if d==0:
curr_err=(1,'division by zero')
return 1
left/=d
else:
return left
def Expr3():
global curr_tok,curr_val,s,curr_err
if curr_tok=='num':
d=curr_val
getToken()
#d=curr_val
return d
elif curr_tok=='minus':
getToken()
return -Expr3()
elif curr_tok=='lp':
getToken()
d=Expr1()
if curr_tok!='rp':
curr_err=(1,'no right parenthesis')
return 1
getToken()
return d
elif curr_tok=='end':
return 1
else:
curr_err=(1,'must by something')
return 1
>>35
Terribly sorry but I live and program in the The Real World(tm); you may have heard if it?. There is no Lisp here, and the world is a brighter place for it.