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

Scott David Daniels Scott.Daniels at Acm.Org
Tue Apr 7 13:09:10 EDT 2009


Grant Edwards wrote:
> I realize that technically all methods are added to classes at
> "run-time", but what I'm talking about is this:
> 
>    import ClientForm
> 
>    def controlEqual(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)
Note:
Here you are checking that self.readonly == self.readonly!
I also dislike the trailing backslashes and over-parenthesizing.
So, I'd do it like this (using the pare to avoid the backslash):
      def controlEqual(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)
...
>    ClientForm.Control.__eq__ = controlEqual
>    ClientForm.Control.__ne__ = controlNotEqual
>    
>    def formEqual(self,other):
>        if len(self.controls) != len(other.controls):
>            return False
>        for (c1,c2) in zip(self.controls,other.controls):
>            if c1 != c2:
>                return False
>        return True
>    
>    def formNotEqual(self,other):
>        return not (self==other)
>    
>    ClientForm.HTMLForm.__eq__ = formEqual
>    ClientForm.HTMLForm.__ne__ = formNotEqual

> It works fine, but it seems like it might be dangerous (or just
> bad form) to insert methods into existing classes like that.
> Perhaps it would be safer to make sure that __eq__, __ne__,
> and __cmp__ don't exist before adding my own?

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)

     class FancyHTMLForm(ClientForm.HTMLForm):
         def __eq__(self,other):
             ...

         def __ne__(self, other):
             return not self.__eq__(other)

You'd have to make sure FancyControl and FancyClientForm get used in
the app.  The latter could be insured by monkey-patching:
     ...
     ClientForm.Control = FancyControl
     ClientForm.HTMLForm = FancyHTMLForm

But substituting monkey-patching for class method insertion seems like
you are going from one quick and dirty technique to a slightly nicer
quick and dirty technique.


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



More information about the Python-list mailing list