Ian Bicking: the old part of his blog

My Python 4k

I was reading this unfinished article on Jython (part of what looks to be very a good but also incomplete series of articles on JVM languages) and he had a few criticisms/suggestions of Python. I've mentioned some minor things that annoy me before, but this made me want to collect them all, and list all the things I wish Python did. Python 3K is already taken, but I'll up the ante -- Python 4K will be the 33% better than even Python 3K. (Note: implementation of Python 4K is left an an exercise for the reader.)

This isn't all backward compatible, but that said I'm not inclined to suggest needless backward incompatibilities either. Some people seem allergic to any "bloat" in a language, and obsess over removing things from builtins and elsewhere. I find this silly. Some people need to learn how to ignore what they don't care about.

So, what's my list?

There's probably some interpreter things I'd like too...

Things I wouldn't do:

Well, that's all for now. Now you know everything I think is wrong with Python (that I can think of right now), and most of what I think would make it right. Looking over it again, I actually don't think it's that pie-in-the-sky, though some parts (like self) are indeed tricky, and involve more than just syntactic additions.

Update:

Created 16 Feb '06
Modified 17 Feb '06

Comments:

Well, I don't really need, or understand deeply, all the advanced/dynamic/metaclass features you're asking for, so I'll comment on the ones I care about.

Definite agreement:

Questions:

I'd add (and I don't follow python-dev, so forgive me if they exist/are coming soon):

# Bill Mill

  • By class-private variables I mean __private, not __magic__. Class-private variables are simply never needed. If you have self.__really_private you can just use self._MyClass_really_private for similar effect (actually self._MyClass__really_private is the identical effect)
  • I think adding ? and ! to function names (or symbol names in general) changes the feel of the language too much. I'd add them if I was starting from zero, but at this point I wouldn't want to use those because it would be too jarring against the bulk of existing code. Dashes are, of course, completely out ;) Also, they conflict with outside naming conventions, making some Python symbols hard to access from other languages. I don't know if this is a big deal in practice, but I think there's something good about using a lowest-common-denominator in naming. Case sensitivity is useful for the same reason (though part of me would like to be case and underscore insensitive, to remove the source of needless style differences).

For the things you would add:

  • There is a proposal for a partial function, which I think is what you mean by currying. Maybe in Python 2.5? I personally don't think it's very readable in practice. lambda actually not half bad for this one case.
  • I agree that a nicer interactive prompt -- roughly based on ipython I imagine -- would be very useful.
  • Local variable dumping is possible currently, but not enabled in the default traceback. I don't know if it should be -- I think it's overwhelming except in interactive environments. It should be included in more interactive environments; maybe standard library support would help. Goes with the __traceback_info__ stuff.
  • GUI library... seems too hard, even for 4K ;) If it hasn't happened outside of the standard library, how can it happen inside? Plus GUIs are the past, the web is the future ;) XUL will rock, though! I'll be all over that.
# Ian Bicking

Bill: Check out PEP 309 for the currying/partial functions thing. http://www.python.org/peps/pep-0309.html. According to the PEP, it'll be in Python 2.5.

# Adrian Holovaty

PartialApplication is officially in for 2.5 I cannot resist pointing our my recipe here:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440557

It's sortof PA++ ;)

# max khesin

I very much want to see 'locals' and 'globals' be sort of accessible keywords much like you suggest 'super' and 'self', and also 'class'. It'd make dealing with the various name-spaces a cinch. Or maybe 'module' instead of 'globals'.

That'd be nice.

# Brantley

Why Python 4k ? Since most of this is not backward compatible, I would be very thanksfull if you began making PEP's for it all.

Personnally, don't understand all the stuff there but I vote for :

About your assertion that GUI is old-style, I'm not totally convinced but I really think, GUI should be able to use bookmarks, protocols and REST style programming. What I see as a limitation in web style programming is the lack for "push" facilities.

Thanks for this wonderfull post.

# Alex Garel

The GUI stuff was really my slightly facetious rejection of those people who complain about how inelegent web programming is, and how it should be more like GUI programming. I think they are just opening a can of worms for themselves, by trying to impose a style of programming they are familiar with to a domain where it is not appropriate. Of course, I also think GUI programming is a bit retro all considered -- I genuinely think that as a user, not just as a programmer. But that only directs my interest, it doesn't really effect the language much one way or the other.

Some of these aren't language extensions per se, but just hard implementation problems: microprocesses are an example of that, as is interpreter startup. I am hopeful that PyPy will open up this kind of development.

# Ian Bicking

Good Ideas but please let strings yield characters on iteration :-) I've much code using string iteration.

And self/cls should'nt be keywords and should be the first parameter of method. Really :)

# Armin Ronacher

String iteration just doesn't make sense. They don't yield characters... they just yield smaller strings. Strings that contain strings that contain strings. Strings just aren't containers in Python -- they are indexable, but to iterate something should be a container. It's only (IMHO) an accident of an earlier Python that didn't have the iterator protocol, that you can iterate over strings. Strings should grow a method like .chars() that yields all the characters. Of course, not backward compatible, but the errors should be obvious ("TypeError: strings are not iterable").

I've been thinking about the self thing more. It's one of the hardest to resolve issues (and I doubt it will be resolved). But I think it would be reasonable if functions defined in a class scope meant something different than a function defined outside of a class scope. So if you were injecting a function definition into a class, it would (reasonably) work just like it does now, with an explicit self parameter. But if you are doing it in a class scope, the metaclass (type) wraps the function in some fashion. It seems less intrusive than class-private variables, even (which are statically determined).

The self parameter also works badly with decorators, though the same might be true if that parameter was removed. Getting a decorator to act properly with a method and with a function is hard.

# Ian Bicking

I certainly agree with some of the changes, like something as basic as proper relative imports. But I think I hear too many "GUI is old style, the web is the future" comments from a lot of programmers that are more over-enthusiasm for new web technologies rather than a careful look at why we keep and discard old/new technologies in general. As others have pointed out, even new asynchronous web technologies are still unidirectional in one sense: the client makes a request, and only then does the server send a reply. Web servers don't initiate requests to web browsers, although traditional networked GUI applications do this all the time. In tech history, we've gone from assembly language (independent of hardware), to portable languages (independent of assembly language), and now to various styles of cross-platform (independent of OS or basic platform). It's not just the web, but any successful model of cross-platform apps that is the future. The web is the future only because the browser is ubiquitous, but in the end I still have to install Firefox, etc. to be able to use the latest web technology. With things like PyGTK and wxPython, I can have the same ubiquity for GUI apps too. It's all the same: I download the app through my browser when I visit a page, or I download the Python script and run it. (P.S. I do agree with a lot of Ian's points in general. Sorry if this sounds like trolling).

# Rob Walker

I don't personally find Python wishlists that interesting, especially the ones which propose language changes, but it's good to see that you've touched on issues with the runtime itself because that is where Python (the platform) should be innovating, or at least fixing itself a fair amount. The problem is that because the language syntax is the thing most people have direct experience with (and one can become superficially acquainted with Python in that way, provoking the "whitespace sucks" arguments offered by detractors/newcomers), people feel more inclined to suggest tweaks which frequently say more about their own habits (at many different levels) rather than to seriously think about some of the harder issues - things like concurrency, performance, predictability, memory usage and library support - and then provide improvements in those areas. And when the harder issues do manage to enter the scene, proposals like optional static typing emerge: the arguably lazy and inadequate approach to dealing with such issues.

Certainly, I don't see Python diminishing in (relative) popularity because of the lack of some language constructs or notation: it's more likely to happen because Python doesn't conveniently work well with or support other, popular technologies, isn't perceived to scale well (in a way that involves convenient programming techniques), or isn't perceived to have good enough documentation - the latter being another story entirely.

# Paul Boddie

My personal feeling is that a multi-line lambda is a mistake, like Guido says. However, I agree with the functionally oriented people that having to use a local named function breaks code locality and tends to make it hard to follow the code in Python written with a more functional flavor.

I think that the right Pythonic answer is to introduce a syntax kind of like ruby blocks where a function call can optionally be followed by a colon, then arg list and a suite underneath and that the arguments and suite would be converted to a local function passed as the last argument to the function. Here is an example:

def open_in( filename, block ):
  f = open( filename )
  try:
     return block( f )
  finally:
     close(f)


max_char = open_in( "foo.txt" ): (f)
  x = 0
  for l in f:
     x = max(x, len(l))
  return x

Or something like that. There are a few warts:

To see what I mean about the return or yield thing, here is an example. First the new form of reduce:

def reduce( l, v, f ):
  for x in l:
    v = f( v, x )
  return initial

Now, the clunky way to write a sum:

sum = reduce( x, 0 ): (a,b)
    return a+b

Vs, the more elegant (IMHO):

sum = reduce( x, 0 ): (a,b)
    a+b

However, sum is a simple contrived example because of course sums, products, any, and all should be built in, and possibly the only real uses involve suites large enough that return or yield is help in understanding, instead of a hindrance.

# Alan Falloon

<pre>
interface IFoo(Bar):
    a = 1
</pre>

Consider this declaration means:

<pre>
def tmp():
    a = 1
IFoo = interface('IFoo', (Bar,), tmp)
</pre>

With this we can express user defined function definition. Interface or class declaration can be emulated by executing tmp and using its local scope as definitions list.
# irg

"I actually like ? and ! in function names, as in Scheme. But I don't think it is worth adding."

Scheme? I thought Ruby invented that! ;)

In any case, I hear you on the whitespace with one exception: I wonder if comments should be exempt from that rule. Sometimes it's just easier to scan down through a file when the important comments are left-aligned.

# Joe Grossberg

Sometimes it's just easier to scan down through a file when the important comments are left-aligned.

Can't you do that right now? I just tried it and it seems to work fine.

# Ian Bicking

Surely you meant to write "py-in-the-sky"?

# Alan Green

I think making self.something spellable as .something would be nice.

# Sergey Schetinin

Not a big fan of that myself. I guess I usually read code in my head on some level, and .something isn't readable in the same way self.something is. Also, that dot is really small. As a separator that's size fine -- good even -- but if it is an independent modifier that's bothersome. Plus I'm not so much looking to save a few keystrokes by taking it out of the signature, as much as bringing some symmetry in signature and use.

# Ian Bicking

"Turning = into an expression. To generalize: dynamic typing adds some usually shallow errors in return for far more expressive code. Assignment as an expression adds some really obnoxious errors (ones that don't raise exceptions) in return for minor expressiveness. That = isn't an expression catches me from making hard bugs almost every day (instead they are easy syntax error bugs).

I'd be fine with := as an assignment-expression, because I wouldn't misspell it. That would certainly be useful. The minimalists would hate this. "

I'm guessing yu'll be using = for equality?

# didier

I'm guessing yu'll be using = for equality?

No, nothing so dramatic; instead adding := as another way to do assignment, allowed in expressions. This is why minimalists would hate it (and not without justification). My real problem making assignment into an expression is that it's really easy to spell == as =, with disasterous consequences. It's really hard to accidentally leave out an = and add in a :, so with := I don't expect that typos will be too much of a problem.

# Ian Bicking

I like the way you're handling self and cls. One thing to note here is that any method that contains a self. is an instance method, any method that contains a cls. is a class method if it doesn't contain a self. as well. If it contains neither, it's a static method. Both the classmethod and staticmethod functions go away.

Another minor point here is that allowing both self. and cls. in the same method gives you access to the class object without any special syntax.

# John Roth

I don't know... I'd consider that much too magical and opaque. »Explicit is better than implicit«, right?

# Matthias Benkard