== Using Python introspection for semi-evil One of the things I write in Python is network daemons. Because it works so nicely, network daemons usually take input as text lines that start with a command word and have whitespace separated arguments. There's a certain amount of eye-rolling tedium in writing code to check that the command word is valid and has the right number of arguments. When I wrote a program that does a lot of this, the tedium finally got to me and I sort of snapped and automated all of the validation through Python's introspection features. The program's basic structure has an object for each connection. Each command is handled by a method function on the object, and the functions all take normal argument lists. (So they are not passed the command line as a big list or anything.) The name of each command method is '((op_))', eg '((op_sample))' to handle the 'sample' command. To check whether the line's first word was a valid command, I just looked to see if the connection's object had an attribute with the appropriate name. (This is a fairly common pattern in Python; see, for example, how [[BaseHTTPServer|http://docs.python.org/lib/module-BaseHTTPServer.html]] handles dispatching _GET_ and _POST_ and so on.) To check that the number of arguments was right, I reached into the handler function I'd just found and fished out how many arguments it expected to be called with (compensating for the additional 'self' argument that method functions get). This isn't at all general, but I didn't need generality; the network daemon's commands all have a fixed number of arguments. The code wound up looking like this: > # in a class: > def op_sample(self, one, two): > ... > > def dispatch(self, line): > # Do we have a line at all? > n = line.split() > if not n: > return False > cword = 'op_' + n[0] > > # Valid command word? > cfunc = getattr(self, cword, None) > if not cfunc: > return False > > # Right argument count? > acnt = cfunc.func_code.co_argcount > if acnt != len(n) > return False > > return cfunc(*n[1:]) (The real version used more elaborate error handling for 'empty line', 'no such command', and 'wrong number of arguments'.) Normally I would have to account for the extra _self_ argument in the function's argument count. But in this code the _n_ list has one extra element (the command word) too, so it balances out. This has the subtle consequence that you can't make ((op_sample)) a _staticmethod_ function, because then it would have the wrong argument count. (I did say this was semi-evil.)