'self' disappearing

Discussion in 'Python' started by Daniel Nouri, Jul 4, 2003.

  1. Daniel Nouri

    Daniel Nouri Guest

    The idea of my simple piece of code is to start from a given module and
    wrap all functions and methods in that module and submodules. FunWrapper is
    the class that I use for wrapping.

    The last two calls of main() in module bla are of interest. While the first
    'foo.bar(c)' works as expected, i.e. prints 'Hello from foo.bar' and
    'Calling bar', the second call bails out with:

    File "seque.py", line 9, in __call__
    self.fun(*args, **kwds)
    TypeError: bar() takes exactly 1 argument (0 given)

    It appears that 'instance.method()' is not the same as
    'klass.method(instance)' in this case. But why? And how do I deal with
    that?


    ---bla.py---

    def a():
    print 'Hello from A'

    def b():
    print 'Hello from B'

    class foo:

    def bar(self):
    print 'Hello from foo.bar'

    def baz(self):
    print 'Hello from foo.baz'

    def main():
    a()
    b()
    c = foo()
    foo.bar(c) #works
    c.bar() #raises TypeError (0 arguments given)

    ---seque.py---

    import types

    class FunWrapper:
    def __init__(self, fun):
    self.fun = fun

    def __call__(self, *args, **kwds):
    print 'Calling', self.fun.__name__
    self.fun(*args, **kwds)

    def _traverse(object):
    for (name, obj) in object.__dict__.items():
    mytype = type(obj)

    if mytype in (types.FunctionType, types.UnboundMethodType):
    wrapper = FunWrapper(obj)
    object.__dict__[name] = wrapper

    elif mytype in (types.ModuleType, types.ClassType):
    _traverse(obj)


    def seque(module, fun):
    _traverse(module)
    module.__dict__[fun]()


    if __name__ == '__main__':
    import bla
    seque(bla, 'main')
    Daniel Nouri, Jul 4, 2003
    #1
    1. Advertising

  2. Daniel Nouri

    Daniel Nouri Guest

    Answering my own question:
    Only a class attribute that is of FunctionType will be automatically
    converted into a bound method by the Python interpreter. If I wanted more
    control, I would have to do it through metaclasses.

    However, my (working) approach now is to return a function instead of a
    class instance, using this simple closure:

    def make_funwrapper(fun):
    def funwrapper(*args, **kwds):
    print 'Calling', fun.__name__
    fun(*args, **kwds)

    return funwrapper

    Note that this requires Python 2.2 or 'from __future__ import
    nested_scopes' because I'm using 'fun' in the nested function.
    Daniel Nouri, Jul 4, 2003
    #2
    1. Advertising

  3. Quoth Daniel Nouri:
    > The idea of my simple piece of code is to start from a given module and
    > wrap all functions and methods in that module and submodules. FunWrapper is
    > the class that I use for wrapping.

    [...]
    > It appears that 'instance.method()' is not the same as
    > 'klass.method(instance)' in this case. But why? And how do I deal with
    > that?


    Your function wrapper implements only the __call__ protocol; you
    also need to handle the descriptor protocol, which is used to
    implement the bound/unbound method business. For example:

    class FunWrapper(object):
    def __init__(self, fun):
    self.fun = fun
    def __call__(self, *args, **kwds):
    print 'Calling', self.fun.__name__
    self.fun(*args, **kwds)
    def __get__(self, *args):
    print 'Getting', self.fun.__name__
    return FunWrapper(self.fun.__get__(*args))

    class Foo(object):
    def bar(*args):
    print 'called with args', args
    bar = FunWrapper(bar)

    foo = Foo()
    foo.bar('a', 'b', 'c')

    You might find Raymond Hettinger's writeup of descriptors useful
    to understand what's going on here:
    <http://users.rcn.com/python/download/Descriptor.htm>

    --
    Steven Taschuk
    "I may be wrong but I'm positive." -- _Friday_, Robert A. Heinlein
    Steven Taschuk, Jul 5, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ralf W. Grosse-Kunstleve
    Replies:
    16
    Views:
    578
    Lonnie Princehouse
    Jul 11, 2005
  2. Ralf W. Grosse-Kunstleve
    Replies:
    18
    Views:
    593
    Bengt Richter
    Jul 11, 2005
  3. Ralf W. Grosse-Kunstleve
    Replies:
    2
    Views:
    399
    Dan Sommers
    Jul 12, 2005
  4. falcon
    Replies:
    0
    Views:
    372
    falcon
    Jul 31, 2005
  5. Bart Kastermans
    Replies:
    6
    Views:
    402
    Bart Kastermans
    Jul 13, 2008
Loading...

Share This Page