2010-10-22 13 views
5
def foo(a, b, c = 0): 
    return a+b 

Tengo docenas de funciones como 'foo', que tienen diferentes números de argumento y nombres. ¿Existe una forma común de obtener los valores de retorno de estas funciones y hacer solo una operación adicional como pformat?¿Es posible modificar el valor de retorno de una función sin definir una nueva función en python?

Sí puedo simplemente generar una nueva función como la siguiente:

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

Pero entonces la nueva función 'envoltorio' es diferente a la antigua 'func', por ejemplo, en número de argumento, 'envoltorio 'tiene solo 2 args -' arg 'y' kw ', pero' func 'puede tener muchas args, como' a ',' b ',' c '.

Solo quiero jugar con el valor de retorno, todo lo demás debe permanecer quieto, ¿es posible?

Gracias!

actualización Por último, este problema se resuelve utilizando decorator módulo y el siguiente parche:

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

Este parche permite decorar métodos acotadas, simplemente lanza el primer argumento 'auto' de distancia, el uso de decorator.decorator se mantiene igual, no se encontraron malos efectos en este momento.

código de ejemplo:

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 





[email protected]:~/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 
>>> 
+0

¿Es la sobrecarga de métodos? – Tauquir

+0

BTW Python no es compatible con la sobrecarga de métodos. – Tauquir

+0

Cambiar sus funciones para reemplazar valores utilizables con cadenas 'pprint.pformat' es realmente una idea realmente mala (tm). No lo hagas Hacer. Eso. –

Respuesta

3

acerca de su problema:

"Pero entonces la nueva función 'envoltorio' es diferente a la anterior 'func', por ejemplo, >> en número de argumento, 'envoltorio' tiene sólo 2 args - 'arg' y 'kw', pero 'func' puede tener muchos >> args, como 'a', 'b', 'c'. "

puede utilizar el módulo de decorator que le permiten crear una firma de preservación de decoradores.

+0

+1 para mencionar el módulo decorador. Es realmente poderoso. También [Venusian] (http://pypi.python.org/pypi/venusian) podría ser útil al tratar con decoradores. –

+0

módulo decorador casi resuelve los problemas, pero parece que no funciona con los métodos vinculados o no vinculados. "Además, observe que puede decorar un método, pero solo antes si se convierte en un método vinculado o libre, es decir, dentro de la clase ....", por lo que es inútil si desea decorar algunos métodos de una clase sin modificar su código fuente por lo que puedo ver – jaimechen

2

decoradores.

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 
+0

¿No debería ser '@ pformat_this'? –

+2

@ S.Loot: functools.wrap no es un decorador que preserva la firma, solo conserva _ _name_ _ y _ _doc_ _ – mouad

2

Los decoradores son esencialmente lo mismo que lo que no desea.

Curioso, investigué esto para python 2.7 y encontré que hay a wealth of meta information available for user defined functions en Tipos llamables -> Funciones definidas por el usuario. Lamentablemente, no hay nada sobre el valor devuelto.

También hay un tipo interno al que puede acceder a través de la función, un objeto de código, en the same page, en Tipos internos -> Objetos de código. Aunque estos tipos internos se proporcionan esencialmente sin promesas de estabilidad de la API, tampoco parece que haya nada que se pueda escribir con respecto al valor devuelto allí.

Tengo la sensación de que si hubiera algo que pudieras hacer directamente, estaría aquí. Ojalá alguien más tenga mejor suerte para ti.

Cuestiones relacionadas