【问题标题】:Is it possible to modify the return value of a function without defining new function in python?是否可以在不在 python 中定义新函数的情况下修改函数的返回值?
【发布时间】:2010-10-22 10:09:30
【问题描述】:
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
>>>

【问题讨论】:

  • BTW Python 不支持方法重载。
  • 更改您的函数以用pprint.pformat 字符串替换可用值实际上是一个非常糟糕的主意(tm)。不。做。它。
  • 似乎改变你的函数的返回值——就像把它们全部变成单个字符串——真的会破坏你应用程序其余部分的功能——或者我错过了什么?
  • @S.Lott & martineau,我忘了提到返回值在新函数中仍然原封不动地返回。额外的操作实际上可以是任何类型的代码,根据您的需要获取一个值并返回一个新值。这更像是猴子修补一个保留输入签名的函数。
  • @chenz“猴子修补功能”并没有多大意义。该概念仅适用于具有大量功能的类和模块。只需创建一个“包装”旧功能的新功能,您会更开心。只写设计b(a(x)) 要简单得多。即使有几十个,普通功能的普通设计也比这种“猴子补丁”概念简单得多。

标签: python


【解决方案1】:

关于你的问题:

"但是那么新的函数'wrapper'和旧的'func'不同,比如>>在参数号中,'wrapper'只有2个args--'arg'和'kw',但是' func' 可能有许多 >> 参数,例如 'a'、'b'、'c'。”

您可以使用decorator 模块,该模块使您能够创建保留签名的装饰器。

【讨论】:

  • +1 提及装饰器模块。它真的很强大。在处理装饰器时,Venusian 也可能很有用。
  • 装饰器模块几乎解决了这些问题,但它似乎不适用于绑定或未绑定的方法。 “此外,请注意你可以装饰一个方法,但只能在 if 成为绑定或非绑定方法之前,即在类内部......”,所以如果你想在不修改其源代码的情况下装饰类的某些方法,它是没有用的据我所知。
【解决方案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

【讨论】:

  • @S.Loot : functools.wrap 不是保留签名的装饰器,它只是保留_ name _ 和_ doc _跨度>
【解决方案3】:

装饰器本质上和你不想要的一样。

好奇,我在 python 2.7 中查看了这个,发现在 Callable types -> User-defined functions 下有a wealth of meta information available for user defined functions。不幸的是,返回的值没有任何内容。

您还可以通过函数访问一个内部类型,一个代码对象,位于the same page 的内部类型 -> 代码对象下。尽管这些内部类型本质上没有对 API 稳定性做出任何承诺,但那里的返回值似乎也没有任何可写的内容。

我有一种感觉,如果有什么你可以直接做的,它就会在这里。希望其他人对你有更好的运气。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多