Monkey-patch Python-klasse

Ik heb een les in een aparte module die ik niet kan veranderen.

from module import MyClass
class ReplaceClass(object)
  ...
MyClass = ReplaceClass

Dit verandert MyClass nergens anders dan in dit bestand. Maar als ik een methode als deze toevoeg

def bar():
   print 123
MyClass.foo = bar

dit zal werken en de foo-methode zal overal elders beschikbaar zijn.

Hoe vervang ik de klas volledig?


Antwoord 1, autoriteit 100%

import module
class ReplaceClass(object):
    ....
module.MyClass = ReplaceClass

Antwoord 2, autoriteit 46%

Vermijd de from ... import(verschrikkelijke;-) manier om barenames te krijgen wanneer je het meest gekwalificeerdenamen nodig hebt. Zodra je de dingen op de juiste Pythonische manier doet:

import module
class ReplaceClass(object): ...
module.MyClass = ReplaceClass

Op deze manier patch je het object module, wat je nodig hebt en werkt als die module voor anderen wordt gebruikt. Met het formulier from ...heb je het module-object gewoon niet bezit(een manier om te kijken naar het flagrante defect van het gebruik van from ...) en dus ben je duidelijk slechter af;-);

De enige manier waarop ik het gebruik van de from-instructie aanbeveel, is door een module vanuit een pakket te importeren:

from some.package.here import amodule

je krijgt dus nog steeds het moduleobject en gebruikt gekwalificeerde namen voor alle namen in die module.


Antwoord 3, autoriteit 24%

Ik ben maar een ei. . . . Misschien is het voor niet-beginners duidelijk, maar ik had het idioom from some.package.module import modulenodig.

Ik moest één methode van GeneralHelpfulClass wijzigen. Dit is mislukt:

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

De code liep, maar maakte geen gebruik van het gedrag dat overbelast was op SpeciallyHelpfulClass.

Dit werkte:

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

Ik vermoed dat het idioom from ... import‘de module krijgt’, zoals Alex schreef, omdat het door andere modules in het pakket zal worden opgepikt. Verder speculerend, lijkt de langere gestippelde verwijzing de module in de naamruimte te brengen met de import door lange gestippelde verwijzing, maar verandert niets aan de module die door andere naamruimten wordt gebruikt. Dus wijzigingen aan de importmodule verschijnen alleen in de naamruimte waar ze zijn gemaakt. Het is alsof er twee exemplaren van dezelfde module zijn, elk beschikbaar onder iets andere referenties.


Antwoord 4, autoriteit 3%

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

Het verdient de voorkeur om de naam van de klasse niet te veranderen tijdens het vervangen, omdat iemand er op de een of andere manier naar heeft verwezen met getattr – wat zal resulteren in een mislukking zoals hieronder

getattr(some_module_name, 'MyClass')–> die zal mislukken als je MyClass hebt vervangen door ReplaceClass!

Other episodes