2010-09-11 10 views
7

Obtuve una función en cierto módulo que quiero redefinir (simulacro) en tiempo de ejecución para fines de prueba. Por lo que yo entiendo, la definición de función no es más que una asignación en python (la definición del módulo en sí es un tipo de función que se está ejecutando). Como dije, quiero hacer esto en la configuración de un caso de prueba, por lo que la función a ser redefinida vive en otro módulo. ¿Cuál es la sintaxis para hacer esto? Por ejemplo, 'el módulo 1' es mi módulo y 'func1' es mi función, en mi caso de prueba que he probado este (sin éxito):¿Cómo redefino las funciones en python?

import module1 

module1.func1 = lambda x: return True 
+2

No necesita 'return' en' lambda'. 'module1.func1 = lambda x: True' debería funcionar. – sastanin

Respuesta

9
import module1 
import unittest 

class MyTest(unittest.TestCase): 
    def setUp(self): 
     # Replace othermod.function with our own mock 
     self.old_func1 = module1.func1 
     module1.func1 = self.my_new_func1 

    def tearDown(self): 
     module1.func1 = self.old_func1 

    def my_new_func1(self, x): 
     """A mock othermod.function just for our tests.""" 
     return True 

    def test_func1(self): 
     module1.func1("arg1") 

un montón de fingida Las bibliotecas proporcionan herramientas para hacer este tipo de burlas, debe investigarlas, ya que es probable que reciba mucha ayuda de ellas.

+0

¿Sabes si puedo redefinir la función usando un cierre? –

+0

También podría usar un lambda como lo hizo en su ejemplo, no tiene por qué ser un método. –

2

Basta con asignar una nueva función o lambda para el antiguo nombre:

>>> def f(x): 
...  return x+1 
... 
>>> f(3) 
4 
>>> def new_f(x): 
...  return x-1 
... 
>>> f = new_f 
>>> f(3) 
2 

funciona también cuando una función es de otro módulo:

### In other.py: 
# def f(x): 
# return x+1 
### 

import other 

other.f = lambda x: x-1 

print other.f(1) # prints 0, not 2 
+0

Como dije, la función está en otro módulo, verifique mi edición. –

+0

Funciona igual. Actualicé la respuesta. – sastanin

3
import foo 

def bar(x): 
    pass 

foo.bar = bar 
+0

La mejor y más simple solución. – Depado

1

Si desea volver a cargar en el archivo foo.py intérprete que se está editando, se puede hacer una función y uso execfile simple de tipo(), pero acabo aprendido que no funciona sin la lista global de todas las funciones (por desgracia), a menos que alguien tiene una idea mejor:

en algún lugar de foo.py archivo:

def refoo(): 
    global fooFun1, fooFun2 
    execfile("foo.py") 

en el intérprete de Python:

refoo() # Ahora tiene su últimas ediciones de foo.py

2

Uso REDEF: http://github.com/joeheyming/redef

import module1 
from redef import redef 

rd_f1 = redef(module1, 'func1', lambda x: True) 

Cuando rd_f1 sale del ámbito o se elimina , func1 volverá a estar normal

+0

Pensé que el alcance refinciado era algo de CPython, y este tipo de cosas no funcionaría en otras plataformas (PyPy, Jython, IronPython). – leewz

+0

all redef does hace es envolver una función o atributo con una nueva función/atributo. cuando el objeto sale del alcance, se llama a la función __delete__, que revierte la declaración de la función a usar la función/atributo anterior. Esto no es un tipo de alcance ref-contado. –

+0

Pero la idea de "el objeto se señala cuando se sale del alcance" depende del recuento de refesiones CPython, ¿no? Por ejemplo, en PyPy, cuando la variable de un objeto de archivo queda fuera del alcance, el objeto NO se recolecta de forma inmediata, por lo que el archivo no se cierra hasta que el recopilador decida hacerlo. – leewz

Cuestiones relacionadas