46 votes

Monkey-patch classe Python

J'ai une classe, située dans un module séparé, que je ne peux pas changer.

 from module import MyClass

class ReplaceClass(object)
  ...

MyClass = ReplaceClass
 

Cela ne change pas MyClass ailleurs que dans ce fichier. Cependant, si j'ajoute une méthode comme celle-ci

 def bar():
   print 123

MyClass.foo = bar
 

cela fonctionnera et la méthode foo sera disponible partout ailleurs.

Comment remplacer la classe complètement?

59voto

Glenn Maynard Points 24451
import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass

29voto

Alex Martelli Points 330805

Éviter l' from ... import (horribles;-) pour obtenir le barenames quand vous avez besoin le plus souvent, sont qualifiés de tous les noms. Une fois que vous faites les choses de la bonne Pythonic façon:

import module

class ReplaceClass(object): ...

module.MyClass = ReplaceClass

De cette façon, vous êtes monkeypatching le module objet, qui est ce que vous avez besoin et de travail lorsque ce module est utilisé pour les autres. Avec l' from ... formulaire, vous venez de ne pas avoir le module objet (une façon de regarder le flagrant défaut de la plupart des gens, l'utilisation de l' from ...) et donc, vous êtes évidemment le pire;-);

La seule façon dont je recommande l'utilisation de l' from déclaration est l'importation d'un module depuis un paquet:

from some.package.here import amodule

donc, vous êtes toujours obtenir le module objet et utiliser les noms complets de tous les noms dans ce module.

12voto

chernevik Points 1141

Je ne suis qu'un œuf . . . . C'est peut-être évident pour les non-débutants, mais j'avais besoin de l' from some.package.module import module idiome.

J'ai dû modifier une méthode de GenerallyHelpfulClass. Cet échec:

import some.package.module

class SpeciallyHelpfulClass(some.package.module.GenerallyHelpfulClass): 
    def general_method(self):...

some.package.module.GenerallyHelpfulClass = SpeciallyHelpfulClass

Le code exécuté, mais n'a pas utilisé les comportements surchargé sur SpeciallyHelpfulClass.

Cela a fonctionné:

from some.package import module

class SpeciallyHelpfulClass(module.GenerallyHelpfulClass): 
    def general_method(self):...

module.GenerallyHelpfulClass = SpeciallyHelpfulClass

Je pense que l' from ... import idiome "reçoit le module', comme Alex l'a écrit, car il sera repris par d'autres modules dans le package. Spéculer en outre, plus parsemée de référence semble apporter le module dans l'espace de noms à l'importation par le long parsemé de référence, mais ne change pas le module utilisé par d'autres espaces de noms. Ainsi, les changements à l'importation du module doit apparaître uniquement dans le nom de l'espace où ils ont été faits. C'est comme si il y avait deux copies d'un même module, chacun disponible en vertu légèrement différentes références.

0voto

shahjapan Points 4043
 import some_module_name

class MyClass(object): 
     ... #copy/paste source class and update/add your logic

some_module_name.MyClass = MyClass
 

Il est préférable de ne pas changer le nom de la classe lors de son remplacement, car quelqu'un pourrait les avoir référencés avec getattr - ce qui entraînerait un échec, comme ci-dessous.

getattr(some_module_name, 'MyClass') -> qui échouera si vous avez remplacé MyClass par ReplaceClass!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X