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

Scott David Daniels Scott.Daniels at Acm.Org
Wed Apr 8 00:02:14 CEST 2009


Grant Edwards wrote:
> On 2009-04-07, Grant Edwards <invalid at invalid> wrote:
>> On 2009-04-07, Scott David Daniels <Scott.Daniels at Acm.Org> wrote:
>>> Grant Edwards wrote:
>>>> I realize that technically all methods are added to classes at
>>>> "run-time", but what I'm talking about is this:
>> ...
>>>>    ClientForm.Control.__eq__ = controlEqual
>>>>    ClientForm.Control.__ne__ = controlNotEqual
>> ...
>>
>>> Well, a more standard approach would be:
>>>      class FancyControl(ClientForm.Control):
>>>          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)
> 
> I like that, except it doesn't work.  Objects instantiated from
> sub-classes of ClientForm.Control break.  I get errors like
> this:
> 
>    Traceback (most recent call last):
>      File "./testit.py", line 141, in <module>
>        f1 = getSocketForm(0)
>      File "./testit.py", line 99, in getSocketForm
>        return getForm("Socket",n)
>      File "./testit.py", line 88, in getForm
>        forms = ClientForm.ParseResponse(response,backwards_compat=False)
>      File "/usr/lib/python2.5/site-packages/ClientForm.py", line 1057, in ParseResponse
>        return _ParseFileEx(response, response.geturl(), *args, **kwds)[1:]
>      File "/usr/lib/python2.5/site-packages/ClientForm.py", line 1128, in _ParseFileEx
>        type, name, attrs, select_default=select_default, index=ii*10)
>      File "/usr/lib/python2.5/site-packages/ClientForm.py", line 2843, in new_control
>        control.add_to_form(self)
>      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.  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.

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



More information about the Python-list mailing list