'bind' functions into methods 
Author Message
 'bind' functions into methods

I have a set of functions, op1(), op2(), etc. with initial argument 'n' the
same.

I want to "bind" them into a class as methods that pass the first argument from
an instance variable.

So far I have the following, but is there a better way to do this?
Can I generate the methods op1, op2, etc. by looping through a list of
functions?
Can I put some shared code for every method call (eg. to check if n is None)?

Kind regards,
Misha

... sample code, on python 2.2.1 ...

def op1(n, dude):
    print "[[[%d -> %d]]]" % (n, dude)

def op2(n, eric, fish):
    print "[[[%d -> %d :: %d]]]" % (n, eric, fish)

class tobj:
    def __init__(self, n=None):
        self.n = n
    def op1(self, *arg, **kwargs):
        return op1(self.n, *arg, **kwargs)
    def op2(self, *arg, **kwargs):
        return op2(self.n, *arg, **kwargs)

# sample usage...

op1(6, 8)
#[[[6 -> 8]]]

op2(6, 3, 9)
#[[[6 -> 3 :: 9]]]

a=tobj(6)
a.op1(dude=8)
#[[[6 -> 8]]]

a.op2(fish=9,eric=3)
#[[[6 -> 3 :: 9]]]

b=tobj()
b.n=7
b.op1(8)
#[[[7 -> 8]]]



Thu, 07 Apr 2005 08:04:15 GMT  
 'bind' functions into methods
Untested ... The idea is to pass a dictionary of functions to the wrapper
object, plus the initial args, then construct the functions themselves as
needed.  You could also construct them "up front" if you prefer.

class TeaWrapper:
    def __init__(self, funcs, initial_args):
        self._funcs = funcs
        self._args = tuple(initial_args)
        # for k, v in funcs.items():
        #    setattr(self, k, self.wrapper(v))

    def __getattr__(self, name):
        try:
            f = self._funcs[name]
        except KeyError:
            raise AttributeError, name

        fun = self.wrapper(f)
        # setattr(self, name, fun) # to cache the attribute
        return fun
    def wrapper(self, f):
        # Assuming you use a Python with nested scopes:
        return lambda *args, **kw: apply(f, self.initial_args + args, kw)

    def wrapper_old_python
        # If you don't ... (move declaration of WrapperClass elsewhere for
        # efficiency)
        class WrapperClass:
            def __init__(self, realfunc, initial_args):
                self.realfunc = realfunc
                self.initial_args = initial_args
            def __call__(self, *args, **kw):
                return apply(self.realfunc, self.initial_args + args, kw)
        return WrapperClass(f, initial_args)

    b = TeaWrapper({'op1' = op1, 'op2' = op2}, (6,))

Quote:

> I have a set of functions, op1(), op2(), etc. with initial argument 'n' the
> same.

> I want to "bind" them into a class as methods that pass the first argument from
> an instance variable.

> So far I have the following, but is there a better way to do this?
> Can I generate the methods op1, op2, etc. by looping through a list of
> functions?
> Can I put some shared code for every method call (eg. to check if n is None)?

> Kind regards,
> Misha

> ... sample code, on Python 2.2.1 ...

> def op1(n, dude):
>     print "[[[%d -> %d]]]" % (n, dude)

> def op2(n, eric, fish):
>     print "[[[%d -> %d :: %d]]]" % (n, eric, fish)

> class tobj:
>     def __init__(self, n=None):
>         self.n = n
>     def op1(self, *arg, **kwargs):
>         return op1(self.n, *arg, **kwargs)
>     def op2(self, *arg, **kwargs):
>         return op2(self.n, *arg, **kwargs)

> # sample usage...

> op1(6, 8)
> #[[[6 -> 8]]]

> op2(6, 3, 9)
> #[[[6 -> 3 :: 9]]]

> a=tobj(6)
> a.op1(dude=8)
> #[[[6 -> 8]]]

> a.op2(fish=9,eric=3)
> #[[[6 -> 3 :: 9]]]

> b=tobj()
> b.n=7
> b.op1(8)
> #[[[7 -> 8]]]

> --
> http://mail.python.org/mailman/listinfo/python-list



Thu, 07 Apr 2005 10:04:06 GMT  
 'bind' functions into methods

Quote:

> I have a set of functions, op1(), op2(), etc. with initial argument 'n' the
> same.

> I want to "bind" them into a class as methods that pass the first argument from
> an instance variable.
> ... sample code, on Python 2.2.1 ...

> def op1(n, dude):
>     print "[[[%d -> %d]]]" % (n, dude)

> def op2(n, eric, fish):
>     print "[[[%d -> %d :: %d]]]" % (n, eric, fish)

> class tobj:
>     def __init__(self, n=None):
>         self.n = n
>     def op1(self, *arg, **kwargs):
>         return op1(self.n, *arg, **kwargs)
>     def op2(self, *arg, **kwargs):
>         return op2(self.n, *arg, **kwargs)

def bind(function, arg1):
    def bound(*args, **kwargs):
        return function(arg1, *args, **kwargs)

    return bound

class tobj:
    def __init__(self, n):
        self.op1 = bind(op1, n)
        self.op2 = bind(op2, n)

Python 2.2: works
Python 2.1: requires "from __future__ import nested_scopes"
Python <=2.0: sorry

        Oren



Thu, 07 Apr 2005 14:41:05 GMT  
 'bind' functions into methods

Quote:

>> I have a set of functions, op1(), op2(), etc. with initial argument 'n' the
>> same.

>> I want to "bind" them into a class as methods that pass the first argument
>from
>> an instance variable.

Thanks for your responses Oren and Jeff, with your help I have worked out a
nice solution.

Oren, your answer is nice and elegant, and does what I asked nicely.
An additional requirement I forgot to mention :) is that the value
of the first argument may change as the instance variable changes...

Jeff, after wrapping my head around your code I think I now understand
what is going on. At first I tried a lambda inside a loop with setattr:

funcs = (op1, op2)
for f in funcs:
    setattr(self, f.func_name, lambda *args, **kw: f(self.n, *args, **kw))

but calling method op1 invoked function op2, so I guess the 'f' in the lambda
is being evaluated on the lambda call, rather than at definition (makes some
sense).

After some mucking around, I put in a wrapper as you suggest, and it works
well:

class tobj:
    def __init__(self, n=None):
        self.n = n
        funcs = (op1, op2)
        for f in funcs:
            setattr(self, f.func_name, self._wrapper(f))

    def _wrapper(self, f):
        return lambda *args, **kw: f(self.n, *args, **kw)

I think this works because the 'f' in _wrapper() is a copy of the 'f' passed
in from the for loop, and the lambda uses the copy rather than the value of 'f'
at the time of the call.

Kind regards,
Misha



Thu, 07 Apr 2005 22:44:40 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Me and python don't agree that my methods are bound

2. I'm in a 'BIND'

3. Language question : function'Access / function'unchecked_Access

4. (documentation 'some-function 'function)

5. Binding 'Self'

6. Tk bind to 'FocusOut' causes segfault

7. tkinter 'command' binding

8. oratcl - bind variable within 'in' condition

9. Binding 'C' Routines to tclsh

10. troubles with 'bind'

11. vrml 2.0 activeX control that allows java methods to access container's methods

12. Recursive methods with :around's and call-next-method results

 

 
Powered by phpBB® Forum Software