11
votes

Comment redéfinir les fonctions de Python?

J'ai une fonction dans un certain module que je veux redéfinir (Mock) au moment de l'exécution à des fins de test. Pour autant que je sache, la définition de la fonction n'est rien de plus qu'une affectation en Python (la définition du module lui-même est une sorte de fonction exécutée). Comme je l'ai dit, je veux le faire dans la configuration d'un cas de test, de sorte que la fonction soit redéfinie des vies dans un autre module. Quelle est la syntaxe pour faire cela? Par exemple, "Module1" est mon module et "Func1" est ma fonction, dans mon témoignage, j'ai essayé ceci (pas de succès): xxx


1 commentaires

Vous n'avez pas besoin retour dans lambda . module1.func1 = lambda x: true devrait fonctionner.


5 Réponses :


2
votes

Il suffit d'attribuer une nouvelle fonction ou Lambda à l'ancien nom: xxx pré>

Il fonctionne également lorsqu'une fonction provient d'un autre module: P>

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


1 commentaires

Comme je l'ai dit, la fonction est dans un autre module, vérifiez mon édition.



12
votes
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")
Lots of mocking libraries provide tools for doing this sort of mocking, you should investigate them as you will likely get a good deal of help from them.

2 commentaires

Savez-vous si je peux redéfinir la fonction en utilisant une fermeture?


Vous pouvez également utiliser une Lambda comme vous l'avez fait dans votre exemple, ce n'est pas obligé d'être une méthode.



5
votes
import foo

def bar(x):
    pass

foo.bar = bar

2 commentaires

Solution la plus simple et la meilleure.


Cela ne fonctionne pas si la barre est définie comme bar (auto, ...) ou le fait-il?



1
votes

Si vous souhaitez recharger dans le fichier d'interpréteur FOO.py que vous modifiez, vous pouvez créer une fonction simple à type et utiliser ExecFile (), mais je viens d'apprendre qu'il ne fonctionne pas sans la liste mondiale. de toutes les fonctions (malheureusement), à moins que quelqu'un ait une meilleure idée:

quelque part dans le fichier foo.py:

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


0 commentaires

2
votes

Utilisez redéfini: http://github.com/joeheyming/redef xxx

Lorsque RD_F1 sort hors de portée ou est supprimé, Func1 redeviendra être de retour à la normale


8 commentaires

Je pensais que la portée du comte Ref était une chose de cpython, et ce genre de chose ne fonctionnerait pas sur d'autres plates-formes (Pypy, Jython, Ironpython).


TOUT RECHERCHE Est-ce que ReDef est une fonction ou un attribut avec une nouvelle fonction / attribut. Lorsque l'objet sort hors de portée, la fonction Supprimer est appelée, ce qui revient la déclaration de fonction à l'aide de l'ancienne fonction / attribut. Ce n'est pas un type de chose compté Re-compté.


Mais l'idée de "objet est signalée quand elle est hors de portée" dépend de CPPHON Re-comptage, non? Par exemple, en PYPY, lorsque la variable d'un objet de fichier est hors de portée, l'objet n'est pas recueilli de manière tout de suite, le fichier n'est donc pas fermé tant que le collecteur ne décide que.


D'après ce que je comprends de votre code, il s'appuie sur __ del __ appelé hors de portée, ainsi que sur appelant del (dans __ sortie __ ) . Je suppose donc que la minorité n'utilise pas CPPHON, ce module a besoin d'une mise en garde. (Explication de PYPY: pyypy.readthedocs. org / fr / Dernières / ... )


Y a-t-il des alternatives à compter sur del ou sortir?


Eh bien, __ sortie __ est garanti, mais vous avez __ sortie __ s'appuyer sur del appelant __ del __ , qui est le problème . Vous devriez directement appeler le nettoyage sur __ sortie __ . Sinon, un ferme () pour permettre à quelqu'un de nettoyer explicitement. La méthode "Portée automatique" serait toujours autorisée, mais découragée par vos docs (comme pour le fichier même CPPHON).


OK, j'ai changé le code pour nettoyer à l'intérieur EXIT . Merci @lewangzhong


Je ne sais pas si c'est correct, même si je ne sais pas non plus si c'est incorrect. Afaik, __ del __ et __ sortie __ moyenne des choses séparées. Je pense que je ferais un fermer () que les deux autres peuvent appeler et le rendre sûr de l'appeler plusieurs fois (soit par un drapeau ou par des opérations idempotentes). En outre, __ __ généralement ne devrait pas être appelé explicitement.