31 Jul 2008 elanthis   » (Journeyer)

Python Annoyances

Forewarning: It’s been years since I last used Python, so I’m very much a “Python n00b” right now. I’m well aware that some of these complaints might entirely just me being an idiot. I would appreciate any comments pointing out said idiocy so I can stop being needlessly annoyed.

Having decided to write Source MUD in Python, I’ve come up with a list of things I find pretty annoying about the language. In no particular order:

  1. Horrendous Documentation

    The Python online manual is just atrocious. The modules are not very well documented, there are far too few examples, and functions don’t actually declare their intended parameters or behavior all too often. Trying to find the proper function to get a job done is hard, and trying to figure out how a particular function is used is even harder. Classes in the standard library are a nightmare to figure out.

    I particularly love the parts of the documentation that include verbiage such as “I can’t be bothered right now to describe…”

  2. Files as Modules

    The Python module system makes organizing code hard. Let’s say I have a dozen or so classes that are all grouped together. I have two choices: I either put them all into one file (e.g. module), or each class goes into a sub-module which somewhat bloats all the code that uses those classes (since I have to type out app.module.submodule.Class instad of app.module.Class).

    Contrast this to Java, which forces one class per file. In that setup, the directories are the module names, and the individual files just mirror the class names. So I can split up a large set of classes into a single module without having unnecessary sub-modules.

    I don’t particularly care for Java’s setup, either, but I find it infinitely better than Python’s. I’d personally prefer something like C++’s, where I the programmer get to explicitly declare modules/namespaces and can freely organize my code however I like.

    This one is really getting on my nerves. The few “too clever” tricks I’ve tried to work around it sadly don’t work. I’m pretty much ready to give up and just start putting all my code into singular huge multi-thousand line files so I don’t have to use stupidly.long.module.names.for.everything.

  3. Classes Are Weak

    Python classes act a lot more like JavaScript’s prototypes, except that they’re not as flexible. I can’t, for example, declare a set of class member variables and default values in the class definition (including documentation). No, instead I have to make a constructor and set all the class members explicitly from that.

    The really annoying part about that is that I can’t make my classes actually mean anything. Since you can just set any member on any class, or freely add or remove methods on any class, and the language can’t do a damn thing to check for simple mistakes (assigning to a misspelled class member name), my code feels really fragile.

    If a variable is set in a class, that actually defines a class variable, not a member. This works out fine for numbers, booleans, and strings, but not so well for hashes, arrays, objects.

    The Python gurus recommend unit testing to make sure code is solid. That’s great. If I wanted to write dozens of lines of boilerplate code in order to make sure stuff worked, I’d have stuck with C++. I want to write less code and be confident in the belief that that code is correct and error free.

    I might be better off with Boo for this particular complaint. I may just end up switching.

    I think to be honest what bothers me most is that the Python way of doing this is not self documenting. I can’t just look at a class and see, at the top, a list of all class members and their default values. I have to look at the __init__ method, which is a bit less clear cut. It moves all the member definitions to the same indentation level as regular method bodies, which makes them stand out less. It also means that member definitions have to have all the extra boilerplate, like the self. in front of the member name. it mixes the member definitions up with any actual initialization logic that __init__ requires. It’s just messy, and makes a class harder to read and understand.

  4. Declarator Inconsistency

    The Python declarator feature is pretty cool. Unfortunately, it’s pointlessly inconsistent. If you want a declarator that has no parameters, you define a simple function. If you want a declarator that takes parameters, however, you must define a function that returns another function. The side effect of this inconsistency is that you end up with two different syntaxes for actually using declarators in the case that you want to call one without any parameters.

    # declarator that takes no parameters
    def dec1(func):
      return func
    
    # declarator that CAN take parameters, but doesn't require them
    def dec2(param=None):
      def actual(func):
        return func
    
    # correct
    @dec1
    def func(): pass
    
    # correct
    @dec2()
    def func(): pass
    
    # correct
    @dec2(param='Test')
    def func(): pass
    
    # incorrect
    @dec1()
    def func(): pass
    
    # incorrect
    @dec2
    def func(): pass
    

    There’s no good reason for that. Both types of declarator should just work the same way.

  5. Variables Aren’t Declared

    I’m not all that interested in static typing of variables (although there are plenty of cases where it’s damn handy). What I am interested in is the need to declare that a variable exists before it can be used.

    Python already kicks up an error when you try to access a variable that hasn’t been defined yet (at runtime, unfortunately), but it will happily let you accidentally create a new variable instead of assigned to the one you intended.

    It’s a really minor complaint, and one that I’m sure a lot of people will disagree about, but I’d really prefer it if I had to declare every variable with a simple “var name = foo” syntax. Likewise, a “const name = foo” would be equally nice.

  6. Unstructured Docstrings

    Alright, sure, I could just decide to do this myself. I do just find it irritating that docstrings don’t enforce any kind of structure, though. It’s really very similar to the idea of Python’s code block structuring requiring indentation: you get better code if you require the code to be well structured. In languages like JavaScript, C, PHP, or Java, it’s not at all uncommon to see novice (or not-so-novice) developers write code with seemingly random indentation. I don’t have a clue how they manage to do that, but they do.

    The same goes with Python’s docstrings. Since they don’t require any kind of special format, they are all too often just worthless bits of text. About as worthless as most code comments (which I’m just as guilty of). I mean, you have to appreciate the silliness of things like:

    def getResults():
      """ Gets the results. """
      return ...
    
    # test if foo is valid
    if foo:
      ...
    

    Really glad that code is documented! It helps so much in understanding what is going on.

    So, I’m sitting here staring at my (quite useless) docstrings, and wondering what I should do with them. Unlike Java, which just uses special comments to document stuff, there isn’t even a standard package for generating good documentation. There’s pydoc, but I can’t for the life of me figure out what the use of that thing is. I think that’s what the official Python documentation is generated with, and you already know my thoughts on that crap.

    I don’t need anything particularly fancy. The bare bones javadoc syntax would be all I really need. Just a way to add a useful description of a function or class, and a way to list out what each parameter is for and what the return value should represent. And a tool to take that and turn it into something pretty to slap up on a website or in README for new developers on the project.

  7. I have a few other complaints, but as those all are being tackled already for Python 3000, I’m not going to bring them up here. No sense complaining about things that are already being fixed,.

Syndicated 2008-07-31 19:40:38 from Sean Middleditch

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!