是否可以修改函数的返回值而无需在python中定义新函数?

时间:2010-10-22 10:09:31

标签: python

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

我有很多像'foo'这样的函数,它们都有不同的参数编号和名称。有没有一种常见的方法可以获取这些函数的返回值,并只对它们执行一个额外的操作,如pformat?

是的我可以生成如下所示的新功能:

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

但是新函数'wrapper'与旧的'func'不同,例如,在参数编号中,'wrapper'只有2个args - 'arg'和'kw',但'func'可能有很多args,比如'a','b','c'。

我只想玩返回值,其他一切应该保持不变,是否可能?

谢谢!

更新 最后,使用decorator模块和以下补丁解决了这个问题:

--- /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(

这个补丁允许你装饰有界方法,它只是抛出第一个'self'参数,decorator.decorator的使用保持不变,现在没有发现任何不良影响。

示例代码:

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 个答案:

答案 0 :(得分:3)

关于您的问题:

  
    

“但是新功能'包装'与原来的'func'不同,例如,参数编号中的&gt;&gt;,'wrapper'只有2个参数 - 'arg'和'kw',但'func'可能有很多&gt;&gt; args,比如'a','b','c'。“

  

您可以使用decorator模块来创建保留签名的装饰器。

答案 1 :(得分:2)

装修。

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

答案 2 :(得分:2)

装饰者基本上与你不想要的相同。

好奇,我调查了python 2.7,发现在Callable类型下有a wealth of meta information available for user defined functions - &gt;用户定义的函数。不幸的是,返回的值没有任何内容。

您还可以通过该功能访问内部类型,代码对象,the same page,内部类型 - &gt;代码对象。即使这些内部类型基本上没有API稳定性的承诺,但似乎没有任何关于返回值的可写内容。

我有一种感觉,如果你有什么可以直接做的话,就会在这里。希望别人能为你带来更好的运气。