Generating a stub class

Carl Banks imbosol at vt.edu
Thu Dec 5 20:29:44 EST 2002


Gerson Kurz wrote:
[snip]
> # generic stub class
> class genericstub:
>    pass
> 
> # create stub for my interface definition
> stub = genericstub()
> for method in dir(myinterface):
> 
>    # skip hidden methods
>    if method[0] <> '_':
> 
>        def instance_method(*args):
>            print "%s called given %s" % (method, args)
> 
>        setattr( stub, method, instance_method )
> 
> # check if stub works
> stub.foo(1,2,3)
> stub.bar()
> 
> ------------(snip here)------------
> 
> This code won't work as (I) expected. It will result in
> 
> foo called given (1, 2, 3)
> foo called given ()
> 
> because, as I understand it, the "method" inside "instance_method" is
> a reference to the loop variable "method" used during the generation
> of the stub class.

Right.  The reference to "method" inside "instance_method" is a global
variable, and refers to the global value of "method" at the time the
function is executed, not at the time it was defined (which is what
you want).


> My solution is creating a "method class" like this:
> 
> class instance_method:
>    def __init__(self, methodname):
>        self.methodname = methodname
> 
>    def __call__(self, *args):
>        print "%s called given %s" % (self.methodname, args)
> 
> which works just fine. Is there an easier solution than that? 

I would say this is the Pythonic way to do it for versions before 2.1.
Starting with Python 2.1, you can use lexical closures:

    from __future__ import nested_scopes

    def define_instance_method(methodname):
        def instance_method(*args):
            print "%s called given %s" % (methodname, args)
        return instance_method

and create the stub method, inside your loop, this way:

        setattr(stub,method,define_instance_method(method))

In Python 2.2, you don't need to import nested_scopes.

Even though Python now has nested scopes, some people still prefer
using a class for this kind of thing.  I prefer to use a closure
myself.


-- 
CARL BANKS



More information about the Python-list mailing list