dynamically generated runtime methods & reflection

Jay Loden python at jayloden.com
Thu Jun 14 06:55:16 CEST 2007


Hi all,

First, apologies if anyone gets this twice, but it took me quite a
while to figure out that Python.org is evidently rejecting all mail
from my mail server because I don't have reverse DNS configured.
Anyway:

I'm not even sure how to phrase this question properly or the right
terminology on this so bear with me. What I'm looking to find out is

a) is there a functionality in Python where I can call a method I have
not defined ahead of time, and based on the method name, change the
functionality of the method at runtime?

b) if not, what is the "Pythonic" approach to the problem outlined
below? Any recommendations on how to approach the problem differently
are welcome.

I've googled and read my Python reference pretty extensively and I've
found some hints but nothing that really answered my questions, so
here I am  :-)  I did figure out that you can overload __getattr__ in
a clas to define a new method at runtime, but I got stuck when I
couldn't figure out how to have a method know what name it was
originally called with. That's the basic question, see below for the
context I'm asking the question in and *why* I want to do the above
:-)

-----

The software product I work on has a socket-based API that can be
accessed directly via telnet & manually typing commands, or by a set
of Perl modules that wrap the socket functionality. I am looking to
write a set of Python modules that match the same functionality.
Basically you can telnet to a port and type something like

    item.list "param1=value1", "param2=value2"

And it will return the results (if any) to you in a given format along
with a response code, e.g. 200 OK or 400 ERROR. The Perl modules just
wrap this so that instead of the above, you can do something like
this:

    $MySocketServer = new SocketServer(Host=>'127.0.0.'1, Port=>'9999');

    if (! $MySocketServer->ListItem(itemName=>$item_name)) {
        print "failed to retrieve list";
        print "reason: " . $MySocketServer->GetErrorMsg();
        exit;
    }


The ListItem() method handles the work of communicating across the
socket, waiting for the response, and determine the success/failure
based on the return code. The part where it gets interesting is that
our Perl modules don't actually have a ListItem() method. Instead,
there is a generalized "_api_func()" method that looks at the name of
the method you called (using Autoload I believe, for any Perlheads out
there), and bases the action taken on the name.

In the example above, for instance, it sees that you called
ListItem(), so it transforms that to item.list and makes the
parameters of the method the parameters that are passed to item.list
via the socket server. Then it takes the response back from the socket
to determine the function return code. If there are any results such
as a list of items, they are then able to be accessed through a
reference to a hash of the results, and there is a GetResultRef
accessor function. In essence, our Perl modules are an incredibly
lightweight, simplistic wrapper for the socket-based API, and almost
all of the work is offloaded to the API implementation server-side.

I welcome any suggestions, feedback, sample code, documentation,
whitepapers etc. The only thing I don't want to have to do is go and
define a separate method for every single one of the possible
permutations of socket commands if I can avoid it!

-----

Thanks in advance,

-Jay



More information about the Python-list mailing list