Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to modify the return value of a function without defining new function in python?

Tags:

python

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
>>>
like image 784
jaimechen Avatar asked Oct 22 '10 10:10

jaimechen


People also ask

Can we define a function without return in Python?

In Python, it is possible to compose a function without a return statement. Functions like this are called void, and they return None, Python's special object for "nothing".

Can a Python function modify argument?

If you pass the object as an argument to a function, then its attributes can be modified in place.

How do I return a value from a function to another function?

To return a value from a function, you must include a return statement, followed by the value to be returned, before the function's end statement. If you do not include a return statement or if you do not specify a value after the keyword return, the value returned by the function is unpredictable.

Can we define a function without return statement?

If no return statement appears in a function definition, control automatically returns to the calling function after the last statement of the called function is executed. In this case, the return value of the called function is undefined.


2 Answers

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.

like image 184
mouad Avatar answered Sep 30 '22 07:09

mouad


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
like image 40
S.Lott Avatar answered Sep 30 '22 07:09

S.Lott