2010-09-11 11 views
7

Ich habe eine Funktion in einem bestimmten Modul, das ich zur Laufzeit für Testzwecke neu definieren (Mock) will. Soweit ich verstehe, ist Funktionsdefinition nichts anderes als eine Zuweisung in Python (die Moduldefinition selbst ist eine Art von Funktion, die ausgeführt wird). Wie ich schon sagte, möchte ich dies beim Aufbau eines Testfalls tun, damit die neu zu definierende Funktion in einem anderen Modul lebt. Was ist die Syntax dafür? Zum Beispiel: ‚module1‘ ist mein Modul und ‚func1‘ meine Funktion ist, in meinem Testfall ich diesen (keinen Erfolg) versucht:Wie definiere ich Funktionen in Python neu?

import module1 

module1.func1 = lambda x: return True 
+2

Sie brauchen nicht 'return' in' lambda'. 'module1.func1 = Lambda x: True' sollte funktionieren. – sastanin

Antwort

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") 

Viel Mock Bibliotheken bieten Werkzeuge für diese Art von Spott, sollten Sie sie untersuchen, wie Sie wahrscheinlich eine Menge Hilfe von ihnen bekommen.

+0

Wissen Sie, ob ich die Funktion mit einem Verschluss neu definieren kann? –

+0

Sie könnten auch ein Lambda wie in Ihrem Beispiel verwenden, es muss keine Methode sein. –

2

einfach eine neue Funktion oder Lambda auf den alten Namen zuweisen:

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

Es funktioniert auch, wenn eine Funktion von einem anderen Modul ist:

### 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

Wie gesagt, die Funktion ist in einem anderen Modul, überprüfe meine Bearbeitung. –

+0

Es funktioniert genauso. Ich habe die Antwort aktualisiert. – sastanin

3
import foo 

def bar(x): 
    pass 

foo.bar = bar 
+0

Einfachste und beste Lösung. – Depado

1

Wenn Sie in die Interpreter-Datei foo.py neu geladen werden sollen, die Sie bearbeiten, können Sie eine einfach zu Typ Funktion und Verwendung execfile(), aber ich habe gerade erfahren, dass es nicht funktioniert ohne die globale Liste aller Funktionen (leider), es sei denn, jemand hat eine bessere Idee:

Irgendwo in der Datei foo.py:

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

im python-Interpreter:

refoo() # Sie haben jetzt Ihre neuesten Änderungen von foo.py

2

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

import module1 
from redef import redef 

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

Wenn rd_f1 den Gültigkeitsbereich verlässt oder gelöscht , func1 wird wieder normal sein

+0

Ich dachte, Ref-gezählte Scope wäre eine CPython-Sache, und diese Art von Sache würde nicht auf anderen Plattformen (PyPy, Jython, IronPython) funktionieren. – leewz

+0

Alle redef-Funktionen umschließen eine Funktion oder ein Attribut mit einer neuen Funktion/einem neuen Attribut. Wenn das Objekt den Gültigkeitsbereich verlässt, wird die __delete__-Funktion aufgerufen, die die Funktionsdeklaration wieder auf die alte Funktion/das alte Attribut zurückführt. Dies ist keine refcounted Umfang Art der Sache. –

+0

Aber die Idee von "Objekt wird signalisiert, wenn es außer Reichweite gerät" ist abhängig von CPython Ref-Counting, nein? Wenn zum Beispiel in PyPy die Variable eines Dateiobjekts den Gültigkeitsbereich verlässt, wird das Objekt NICHT sofort von einem Garbage-Collected erfasst, sodass die Datei erst geschlossen wird, wenn sich der Collector entschließt. – leewz

Verwandte Themen