tags:

views:

87

answers:

3
def foo(a, b, c = 0):
    return a+b

I have dozens of functions like 'foo', which all have different argument numbers and names. Is there a common way that I can get the return values of these functions and do just a single extra operation like pformat to them?

Yes I can just generate a new function like the following:

func = ...  # func can be got using getattr by name
def wrapper(*arg, **kw):
    data = func(*arg, **kw)
    return pprint.pformat(data)
return wrapper

But then the new function 'wrapper' is different to the old one 'func', for example, in argument number, 'wrapper' has only 2 args--'arg' and 'kw', but 'func' may have many args, like 'a', 'b', 'c'.

I just want play with the return value, everything else should stay still, is it possible?

Thanks!

Update Finally this problem was solved using decorator module and the following patch:

--- /home/jaime/cache/decorator-3.2.0/src/decorator.py  2010-05-22 23:53:46.000000000 +0800
+++ decorator.py    2010-10-28 14:55:11.511140589 +0800
@@ -66,9 +66,12 @@
             self.name = '_lambda_' 
             self.doc = func.__doc__
             self.module = func.__module__
-            if inspect.isfunction(func):
+            if inspect.isfunction(func) or inspect.ismethod(func):
                 argspec = inspect.getargspec(func)
                 self.args, self.varargs, self.keywords, self.defaults = argspec
+                if inspect.ismethod(func):
+                    self.args = self.args[1:] # Remove the useless 'self' arg
+                    argspec = inspect.ArgSpec(self.args, self.varargs, self.keywords, self.defaults)
                 for i, arg in enumerate(self.args):
                     setattr(self, 'arg%d' % i, arg)
                 self.signature = inspect.formatargspec(

This patch allows you to decorate bounded methods, it just throws the first 'self' argument away, usage of decorator.decorator stays the same, no bad effects found right now.

example code:

def __getattr__(self, attr):
    def pformat_wrapper(f, *args, **kw):
        data = f(*args, **kw)
        return pprint.pformat(data, indent = 4)

    method = getattr(self.ncapi, attr)
    return decorator(pformat_wrapper, method) # Signature preserving decorating





jaime@westeros:~/bay/dragon.testing/tests$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import decorator
>>> class A:
...   def f(self):
...       pass
... 
>>> a = A()
>>> a.f
<bound method A.f of <__main__.A instance at 0xb774a20c>>
>>> def hello(f, *args, **kw):
...     print 'hello'
...     return f(*args, **kw)
... 
>>> f1 = decorator.decorator(hello, a.f)
>>> f1()
hello
>>>
+3  A: 

Decorators.

from functools import wraps
def pformat_this( someFunc ):
    @wraps( someFunc )
    def wrapper(*arg, **kw):
        data = someFunc(*arg, **kw)
        return pprint.pformat(data)
    return wrapper


@pformat_this
def foo(a, b, c = 0):
    return a+b
S.Lott
Shouldn't that be `@pformat_this`?
Space_C0wb0y
@S.Loot : functools.wrap is not a signature-preserving decorators , it just preserve _ _name_ _ and _ _doc_ _
singularity
+1  A: 

Decorators are essentially the same as what you do not want.

Getting curious, I looked into this for python 2.7, and found that there is a wealth of meta information available for user defined functions under Callable types -> User-defined functions. Unfortunately, there is nothing about the returned value.

There is also an internal type you can access through the function, a code object, on the same page, under Internal types -> Code objects. Even though these internal types are essentially provided with no promises to API stability, there doesn't seem to be anything writable with regard to the returned value there either.

I have a feeling that if there were anything you could do directly, it would be here. Hopefully someone else has better luck for you.

AndrewBC
+2  A: 

About your problem :

"But then the new function 'wrapper' is different to the old one 'func', for example, >> in argument number, 'wrapper' has only 2 args--'arg' and 'kw', but 'func' may have many >> args, like 'a', 'b', 'c'."

you can use the decorator module which enable you to create a signature-preserving decorators.

singularity
+1 to mention the decorator module. It's really powerful. Also [Venusian](http://pypi.python.org/pypi/venusian) might be useful when dealing with decorators.
Attila Oláh
decorator module almost solves the problems, but it seems does not work with bound or unbound methods. "Moreover, notice that you can decorate a method, but only before if becomes a bound or unbound method, i.e. inside the class....", so it's useless if you want to decorating some methods of a class without modifying its source code as far as I can see.
chenz