Adding method to class at run-time: bad style?

Scott David Daniels Scott.Daniels at Acm.Org
Tue Apr 7 19:09:20 EDT 2009


Grant Edwards wrote:
> On 2009-04-07, Scott David Daniels <Scott.Daniels at Acm.Org> wrote:
> 
>>>      File "/usr/lib/python2.5/site-packages/ClientForm.py", line 2016, in add_to_form
>>>        Control.add_to_form(self, form)
>>>    TypeError: unbound method add_to_form() must be called with FancyControl instance as first argument (got CheckboxControl instance instead)
>> OK, that is one of the problems with monkey-patching.  What happened
>> is ClientForm apparently defines subclasses of Control such as
>> CheckboxControl.
> 
> Right.  Control is just a base class, and changing it to a
> "different" class after sub-classes have been defined pulls the
> rug out from under things.  Had I thought about it for a
> minute, I should have known that would happen.  The working
> patch tweaks the class in-place, so it works OK.
> 
>> The monkey-patching only happens after the ClientForm module
>> has been executed (first import), and the monkey-patching
>> happens after all of that.  So now the "tack it into the
>> class" method looks a bit better if you cannot simply add your
>> requirement to the ClientForm source.
> 
> That's obviously the "right thing", but it makes portability
> more of an issue (I would have to archive/distribute ClientForm
> source and users would have to install the customized version
> of ClientForm).
> 
> Of course there's always the chance that my version of
> monkey-patching will stop working with a different version of
> ClientForm.  We'll burn that bridge when we come to it.
> 

What you might use as a half-way measure:

     class Mixin:  # or class Mixin(object) if new-style:
         def __eq__(self, other):
             return (self.type == other.type
                 and self.name == other.name
                 and self.value == other.value
                 and self.disabled == other.disabled
                 and self.readonly == self.readonly)

         def __ne__(self, other):
             return not self.__eq__(other)
     ...(including  FancyHTMLForm) ...
     class FancyControl(MixIn, ClientForm.Control): pass
     class FancyCheckboxControl(MixIn, ClientForm.CheckboxControl): pass
     ...
     ClientForm.HTMLForm = FancyHTMLForm
     ClientForm.Control = FancyControl
     ClientForm.CheckboxControl = FancyCheckboxControl

--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list