在Python中是否可以不定义新函数而修改函数的返回值?

5 投票
3 回答
3359 浏览
提问于 2025-04-16 05:54
def foo(a, b, c = 0):
    return a+b

我有很多像'foo'这样的函数,它们的参数数量和名称都不一样。我想知道有没有一种通用的方法,可以获取这些函数的返回值,然后对它们进行一次简单的操作,比如格式化输出。

当然,我可以像下面这样生成一个新的函数:

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'只有两个参数——'arg'和'kw',而'func'可能有很多参数,比如'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 个回答

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

装饰器其实就是你不想要的东西。

出于好奇,我查了一下Python 2.7,发现关于用户自定义函数有很多元信息可以参考,具体在可调用类型下的用户定义函数部分。不过,遗憾的是,关于返回值的内容并没有找到。

你还可以通过函数访问一个内部类型,叫做代码对象,具体信息可以在同一页面的内部类型下找到。虽然这些内部类型基本上没有保证会稳定,但在返回值方面似乎也没有什么可以写的东西。

我感觉如果有什么可以直接操作的东西,应该就在这里。希望其他人能帮你找到更好的解决办法。

4

关于你的问题:

“但是新的函数 'wrapper' 和旧的函数 'func' 不一样,比如在参数数量上,'wrapper' 只有两个参数——'arg' 和 'kw',而 'func' 可能有很多参数,比如 'a'、'b'、'c'。”

你可以使用decorator模块,这个模块可以帮助你创建保留函数签名的装饰器。

撰写回答